From 3a6e9d92eab50ba94260a8fca01e8326ff37933f Mon Sep 17 00:00:00 2001 From: groth-its Date: Sat, 4 Sep 2021 01:11:14 +0200 Subject: [PATCH 001/185] Add / correct home assistant device classes Add missing and correct existing home assistant device classes that are currently available in home assistant releases for auto discovery. --- tasmota/xdrv_12_home_assistant.ino | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tasmota/xdrv_12_home_assistant.ino b/tasmota/xdrv_12_home_assistant.ino index 5fb759f15..d224b4cd5 100644 --- a/tasmota/xdrv_12_home_assistant.ino +++ b/tasmota/xdrv_12_home_assistant.ino @@ -39,12 +39,12 @@ const char kHAssJsonSensorUnits[] PROGMEM = "ppm|ppm|ppb|R|G|B|" D_UNIT_KELVIN "| |"; const char kHAssJsonSensorDevCla[] PROGMEM = - "dev_cla\":\"temperature|ic\":\"mdi:weather-rainy|dev_cla\":\"pressure|dev_cla\":\"pressure|" - "dev_cla\":\"power|dev_cla\":\"battery|ic\":\"mdi:alpha-a-circle-outline|ic\":\"mdi:leak|ic\":\"mdi:current-ac|dev_cla\":\"humidity|dev_cla\":\"illuminance|" + "dev_cla\":\"temperature|dev_cla\":\"temperature|dev_cla\":\"pressure|dev_cla\":\"pressure|" + "dev_cla\":\"power|dev_cla\":\"battery|dev_cla\":\"current|ic\":\"mdi:leak|ic\":\"mdi:current-ac|dev_cla\":\"humidity|dev_cla\":\"illuminance|" "ic\":\"mdi:cup-water|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|" - "ic\":\"mdi:air-filter|ic\":\"mdi:air-filter|ic\":\"mdi:air-filter|ic\":\"mdi:alpha-f-circle-outline|dev_cla\":\"power|ic\":\"mdi:progress-clock|" - "dev_cla\":\"power|dev_cla\":\"power|dev_cla\":\"power|ic\":\"mdi:alpha-v-circle-outline|ic\":\"mdi:scale|dev_cla\":\"power|" - "ic\":\"mdi:molecule-co2|ic\":\"mdi:molecule-co2|ic\":\"mdi:air-filter|" + "dev_cla\":\"pm1|dev_cla\":\"pm25|dev_cla\":\"pm10|dev_cla\":\"power_factor|dev_cla\":\"power|ic\":\"mdi:progress-clock|" + "dev_cla\":\"power|dev_cla\":\"energy|dev_cla\":\"energy|dev_cla\":\"voltage|ic\":\"mdi:scale|dev_cla\":\"energy|" + "dev_cla\":\"carbon_dioxide|dev_cla\":\"carbon_dioxide|dev_class\":\"volatile_organic_compounds|" "ic\":\"mdi:palette|ic\":\"mdi:palette|ic\":\"mdi:palette|ic\":\"mdi:temperature-kelvin|ic\":\"mdi:ruler|dev_cla\":\"illuminance|"; // List of sensors ready for discovery From 628c00f0906bd55b38820a323c1808eba9433335 Mon Sep 17 00:00:00 2001 From: Lenbok Date: Fri, 29 Oct 2021 19:43:10 +1300 Subject: [PATCH 002/185] Reflect PVVX firmware reed switch status The first bit of the flag field reflects reed switch status so this device can additionally be used to monitor the status of a door. --- tasmota/xsns_62_esp32_mi_ble.ino | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tasmota/xsns_62_esp32_mi_ble.ino b/tasmota/xsns_62_esp32_mi_ble.ino index cb9548e6e..761d1c0de 100644 --- a/tasmota/xsns_62_esp32_mi_ble.ino +++ b/tasmota/xsns_62_esp32_mi_ble.ino @@ -1586,6 +1586,10 @@ void MI32ParseATCPacket(const uint8_t * _buf, uint32_t length, const uint8_t *ad MIBLEsensors[_slot].bat = ppv_packet->battery_level; MIBLEsensors[_slot].eventType.bat = 1; + MIBLEsensors[_slot].Btn = (ppv_packet->flags) & 0x1; // First bit is reed switch status + MIBLEsensors[_slot].eventType.Btn = 1; + MIBLEsensors[_slot].feature.Btn = 1; + if(MI32.option.directBridgeMode) { MIBLEsensors[_slot].shallSendMQTT = 1; MI32.mode.shallTriggerTele = 1; @@ -3271,4 +3275,4 @@ bool Xsns62(uint8_t function) #endif // CONFIG_IDF_TARGET_ESP32 or CONFIG_IDF_TARGET_ESP32C3 #endif // ESP32 -#endif \ No newline at end of file +#endif From bf8a8c621e04b07f589b0091c90d94bf52523d0b Mon Sep 17 00:00:00 2001 From: kruzer Date: Mon, 1 Nov 2021 12:31:08 +0100 Subject: [PATCH 003/185] added config variable StepPixels --- tasmota/i18n.h | 1 + tasmota/settings.h | 3 ++- tasmota/xlgt_01_ws2812.ino | 15 +++++++++++++-- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 9c8aed881..73d8ade89 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -477,6 +477,7 @@ #define D_CMND_FADE "Fade" #define D_CMND_PALETTE "Palette" #define D_CMND_PIXELS "Pixels" +#define D_CMND_STEPPIXELS "StepPixels" #define D_CMND_RGBWWTABLE "RGBWWTable" #define D_CMND_ROTATION "Rotation" #define D_CMND_SCHEME "Scheme" diff --git a/tasmota/settings.h b/tasmota/settings.h index 4e41c5916..8c903d6a4 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -733,8 +733,9 @@ typedef struct { uint8_t shd_leading_edge; // F5B uint16_t shd_warmup_brightness; // F5C uint8_t shd_warmup_time; // F5E + uint8_t light_step_pixels; // F5F - uint8_t free_f5f[61]; // F5F - Decrement if adding new Setting variables just above and below + uint8_t free_f5f[60]; // F60 - Decrement if adding new Setting variables just above and below // Only 32 bit boundary variables below diff --git a/tasmota/xlgt_01_ws2812.ino b/tasmota/xlgt_01_ws2812.ino index a7e7c9927..89e8dc66c 100644 --- a/tasmota/xlgt_01_ws2812.ino +++ b/tasmota/xlgt_01_ws2812.ino @@ -40,10 +40,10 @@ const uint8_t WS2812_SCHEMES = 8; // Number of WS2812 schemes const char kWs2812Commands[] PROGMEM = "|" // No prefix - D_CMND_LED "|" D_CMND_PIXELS "|" D_CMND_ROTATION "|" D_CMND_WIDTH ; + D_CMND_LED "|" D_CMND_PIXELS "|" D_CMND_ROTATION "|" D_CMND_WIDTH "|" D_CMND_STEPPIXELS ; void (* const Ws2812Command[])(void) PROGMEM = { - &CmndLed, &CmndPixels, &CmndRotation, &CmndWidth }; + &CmndLed, &CmndPixels, &CmndRotation, &CmndWidth, &CmndStepPixels }; #include @@ -568,6 +568,17 @@ void CmndPixels(void) ResponseCmndNumber(Settings->light_pixels); } +void CmndStepPixels(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= WS2812_MAX_LEDS)) { + Settings->light_step_pixels = XdrvMailbox.payload; + Ws2812Clear(); + Light.update = true; + } + ResponseCmndNumber(Settings->light_step_pixels); +} + + void CmndRotation(void) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < Settings->light_pixels)) { From 42267c2bd9685cadf014910c5b02a1e83f5f5453 Mon Sep 17 00:00:00 2001 From: kruzer Date: Wed, 3 Nov 2021 00:03:06 +0100 Subject: [PATCH 004/185] Working effects of gradual highligting based on scheme 13, bitwise rotation settings, fade effect --- tasmota/xlgt_01_ws2812.ino | 118 +++++++++++++++++++++++++++++++++++-- 1 file changed, 112 insertions(+), 6 deletions(-) diff --git a/tasmota/xlgt_01_ws2812.ino b/tasmota/xlgt_01_ws2812.ino index 89e8dc66c..dd91ebe5d 100644 --- a/tasmota/xlgt_01_ws2812.ino +++ b/tasmota/xlgt_01_ws2812.ino @@ -37,7 +37,7 @@ #define XLGT_01 1 -const uint8_t WS2812_SCHEMES = 8; // Number of WS2812 schemes +const uint8_t WS2812_SCHEMES = 9; // Number of WS2812 schemes const char kWs2812Commands[] PROGMEM = "|" // No prefix D_CMND_LED "|" D_CMND_PIXELS "|" D_CMND_ROTATION "|" D_CMND_WIDTH "|" D_CMND_STEPPIXELS ; @@ -166,6 +166,7 @@ WsColor kHanukkah[2] = { 0,0,255, 255,255,255 }; WsColor kwanzaa[3] = { 255,0,0, 0,0,0, 0,255,0 }; WsColor kRainbow[7] = { 255,0,0, 255,128,0, 255,255,0, 0,255,0, 0,0,255, 128,0,255, 255,0,255 }; WsColor kFire[3] = { 255,0,0, 255,102,0, 255,192,0 }; +WsColor kStairs[2] = { 0,0,0, 255,255,255 }; ColorScheme kSchemes[WS2812_SCHEMES -1] = { // Skip clock scheme kIncandescent, 2, kRgb, 3, @@ -173,7 +174,8 @@ ColorScheme kSchemes[WS2812_SCHEMES -1] = { // Skip clock scheme kHanukkah, 2, kwanzaa, 3, kRainbow, 7, - kFire, 3 }; + kFire, 3, + kStairs, 2 }; uint8_t kWidth[5] = { 1, // Small @@ -399,6 +401,106 @@ void Ws2812Bars(uint32_t schemenr) Ws2812StripShow(); } +void Ws2812Steps(uint32_t schemenr) +{ +#if (USE_WS2812_CTYPE > NEO_3LED) + RgbwColor c; + c.W = 0; +#else + RgbColor c; +#endif + + ColorScheme scheme = kSchemes[schemenr]; + if(0==scheme.colors[0].blue && 0==scheme.colors[0].red && 0==scheme.colors[0].green && scheme.count==2){ + scheme.colors[1].red = Settings->light_color[0]; + scheme.colors[1].green = Settings->light_color[1]; + scheme.colors[1].blue = Settings->light_color[2]; + } + uint8_t scheme_count=scheme.count; + + if(Settings->light_fade){ + scheme_count=Settings->ws_width[WS_HOUR];//Width4 + } + + WsColor mcolor[scheme_count]; + uint8_t color_start=0; + uint8_t color_end=1; + + if(Settings->light_rotation & 0x01){ + color_start=1; + color_end=0; + } + + if(Settings->light_fade){ + + for(uint32_t i=1; i < scheme_count - 1; i++){ + mcolor[i].red = (uint8_t) wsmap(i, 0, scheme_count, scheme.colors[color_start].red, scheme.colors[color_end].red); + mcolor[i].green = (uint8_t) wsmap(i, 0, scheme_count, scheme.colors[color_start].green, scheme.colors[color_end].green); + mcolor[i].blue = (uint8_t) wsmap(i, 0, scheme_count, scheme.colors[color_start].blue, scheme.colors[color_end].blue); + } + } else { + memcpy(mcolor, scheme.colors, sizeof(mcolor)); + } + mcolor[0].red=scheme.colors[color_start].red; + mcolor[0].green=scheme.colors[color_start].green; + mcolor[0].blue=scheme.colors[color_start].blue; + mcolor[scheme_count-1].red=scheme.colors[color_end].red; + mcolor[scheme_count-1].green=scheme.colors[color_end].green; + mcolor[scheme_count-1].blue=scheme.colors[color_end].blue; + + + float dimmer = 100 / (float)Settings->light_dimmer; + for (uint32_t i = 0; i < scheme_count; i++) { + float fmyRed = (float)mcolor[i].red / dimmer; + float fmyGrn = (float)mcolor[i].green / dimmer; + float fmyBlu = (float)mcolor[i].blue / dimmer; + mcolor[i].red = (uint8_t)fmyRed; + mcolor[i].green = (uint8_t)fmyGrn; + mcolor[i].blue = (uint8_t)fmyBlu; + } + + uint32_t speed = Settings->light_speed; + int32_t current_position = Light.strip_timer_counter / speed; + + //all is shown already + if(current_position > Settings->light_pixels / Settings->light_step_pixels + scheme_count ) { +// AddLog(LOG_LEVEL_INFO, PSTR("spd:%d cpos:%d tc:%d"), speed,current_position,Light.strip_timer_counter); + return; + } + + int32_t colorIndex; + //int32_t leading_step = current_position / Settings->light_step_pixels; + int32_t step_nr; + /*if( Light.strip_timer_counter % speed == 0){ + AddLog(LOG_LEVEL_INFO, PSTR("spd:%d cpos:%d lead:%d tc:%d"), speed,current_position,leading_step,Light.strip_timer_counter); + }*/ + + for (uint32_t i = 0; i < Settings->light_pixels; i++) { + step_nr = i / Settings->light_step_pixels; + colorIndex = current_position - step_nr; + if(colorIndex < 0) colorIndex = 0; + if(colorIndex > scheme_count - 1) colorIndex = scheme_count - 1; + c.R = mcolor[colorIndex].red; + c.G = mcolor[colorIndex].green; + c.B = mcolor[colorIndex].blue; + if( current_position % 3 == 0){ + //AddLog(LOG_LEVEL_INFO, PSTR("spd:%d cpos:%d lead:%d tc:%d"), speed,current_position,leading_step,Light.strip_timer_counter); + if(i < 15){ + // AddLog(LOG_LEVEL_INFO, PSTR("s_n:%d cidx:%d "), step_nr, colorIndex); + } + } +/* if(i < 2){ + AddLog(LOG_LEVEL_INFO, PSTR("s_n:%d cidx:%d "), step_nr, colorIndex); + }*/ + if(Settings->light_rotation & 0x02){ + strip->SetPixelColor(Settings->light_pixels - i - 1, c); + } else { + strip->SetPixelColor(i, c); + } + } + Ws2812StripShow(); +} + void Ws2812Clear(void) { strip->ClearTo(0); @@ -496,10 +598,14 @@ void Ws2812ShowScheme(void) } break; default: - if (1 == Settings->light_fade) { - Ws2812Gradient(scheme -1); - } else { - Ws2812Bars(scheme -1); + if(Settings->light_step_pixels > 0){ + Ws2812Steps(scheme -1); + } else { + if (1 == Settings->light_fade) { + Ws2812Gradient(scheme -1); + } else { + Ws2812Bars(scheme -1); + } } Ws2812.show_next = 1; break; From d033c2b5eec723d87a22ae2aa16d78ab7d059157 Mon Sep 17 00:00:00 2001 From: Charles Date: Sat, 6 Nov 2021 12:35:53 +0100 Subject: [PATCH 005/185] Update xdrv_39_thermostat.ino Show state/values on WebUI --- tasmota/xdrv_39_thermostat.ino | 104 +++++++++++++++++++++++++++------ 1 file changed, 87 insertions(+), 17 deletions(-) diff --git a/tasmota/xdrv_39_thermostat.ino b/tasmota/xdrv_39_thermostat.ino index d016c3edc..209ecd830 100644 --- a/tasmota/xdrv_39_thermostat.ino +++ b/tasmota/xdrv_39_thermostat.ino @@ -1269,6 +1269,28 @@ void ThermostatVirtualSwitchCtrState(uint8_t ctr_output) MqttPublish(domoticz_in_topic); } +uint8_t ThermostatGetDutyCycle(uint8_t ctr_output) +{ + uint8_t value = 0; + if ( (Thermostat[ctr_output].status.controller_mode == CTR_PI) + || ((Thermostat[ctr_output].status.controller_mode == CTR_HYBRID) + &&(Thermostat[ctr_output].status.phase_hybrid_ctr == CTR_HYBRID_PI))) { + value = Thermostat[ctr_output].time_total_pi / Thermostat[ctr_output].time_pi_cycle; + } + else if ( (Thermostat[ctr_output].status.controller_mode == CTR_RAMP_UP) + || ((Thermostat[ctr_output].status.controller_mode == CTR_HYBRID) + &&(Thermostat[ctr_output].status.phase_hybrid_ctr == CTR_HYBRID_RAMP_UP))) { + if (Thermostat[ctr_output].status.status_output == IFACE_ON) { + value = 100; + } + else { + value = 0; + } + } + return value; +} + + void ThermostatDebug(uint8_t ctr_output) { char result_chr[FLOATSZ]; @@ -1950,23 +1972,8 @@ void CmndCtrDutyCycleRead(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { uint8_t ctr_output = XdrvMailbox.index - 1; - uint8_t value = 0; - if ( (Thermostat[ctr_output].status.controller_mode == CTR_PI) - || ((Thermostat[ctr_output].status.controller_mode == CTR_HYBRID) - &&(Thermostat[ctr_output].status.phase_hybrid_ctr == CTR_HYBRID_PI))) { - value = Thermostat[ctr_output].time_total_pi / Thermostat[ctr_output].time_pi_cycle; - } - else if ( (Thermostat[ctr_output].status.controller_mode == CTR_RAMP_UP) - || ((Thermostat[ctr_output].status.controller_mode == CTR_HYBRID) - &&(Thermostat[ctr_output].status.phase_hybrid_ctr == CTR_HYBRID_RAMP_UP))) { - if (Thermostat[ctr_output].status.status_output == IFACE_ON) { - value = 100; - } - else { - value = 0; - } - } - ResponseCmndIdxNumber((int)value); + + ResponseCmndIdxNumber((int)ThermostatGetDutyCycle(ctr_output) ); } } @@ -1984,6 +1991,60 @@ void CmndEnableOutputSet(void) } } + + +/*********************************************************************************************\ + * Web UI +\*********************************************************************************************/ + +// xdrv_39_thermostat.ino +#define D_THERMOSTAT "Thermostat" +#define D_THERMOSTAT_SET_POINT "Set Point" +#define D_THERMOSTAT_SENSOR "Sensor" +#define D_THERMOSTAT_GRADIENT "Gradient" +#define D_THERMOSTAT_DUTY_CYCLE "Duty Cycle" + +#ifdef USE_WEBSERVER +const char HTTP_THERMOSTAT_INFO[] PROGMEM = "{s}" D_THERMOSTAT "{m}%s{e}"; +const char HTTP_THERMOSTAT_TEMPERATURE[] PROGMEM = "{s}%s " D_TEMPERATURE "{m}%*_f " D_UNIT_DEGREE "%c{e}"; +const char HTTP_THERMOSTAT_DUTY_CYCLE[] PROGMEM = "{s}" D_THERMOSTAT_DUTY_CYCLE "{m}%d " D_UNIT_PERCENT "{e}"; + +#endif // USE_WEBSERVER + +void ThermostatShow(uint8_t ctr_output) +{ +#ifdef USE_WEBSERVER + + if (Thermostat[ctr_output].status.thermostat_mode == THERMOSTAT_OFF) { + WSContentSend_P(HTTP_THERMOSTAT_INFO, D_DISABLED ); + + } else { + char c_unit = Thermostat[ctr_output].status.temp_format==TEMP_CELSIUS ? D_UNIT_CELSIUS[0] : D_UNIT_FAHRENHEIT[0]; + float f_temperature ; + + WSContentSend_P(HTTP_THERMOSTAT_INFO, D_ENABLED ); + + f_temperature = Thermostat[ctr_output].temp_target_level / 10.0f ; + WSContentSend_PD(HTTP_THERMOSTAT_TEMPERATURE, D_THERMOSTAT_SET_POINT, Settings->flag2.temperature_resolution, &f_temperature, c_unit); + + f_temperature = Thermostat[ctr_output].temp_measured / 10.0f; + WSContentSend_PD(HTTP_THERMOSTAT_TEMPERATURE, D_THERMOSTAT_SENSOR, Settings->flag2.temperature_resolution, &f_temperature, c_unit); + + int16_t value = Thermostat[ctr_output].temp_measured_gradient; + if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { + value = ThermostatCelsiusToFahrenheit((int32_t)Thermostat[ctr_output].temp_measured_gradient, TEMP_CONV_RELATIVE); + } + f_temperature = value / 1000.0f; + WSContentSend_PD(HTTP_THERMOSTAT_TEMPERATURE, D_THERMOSTAT_GRADIENT, Settings->flag2.temperature_resolution, &f_temperature, c_unit); + WSContentSend_P(HTTP_THERMOSTAT_DUTY_CYCLE, ThermostatGetDutyCycle(ctr_output) ); + } + + +#endif // USE_WEBSERVER +} + + + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -2029,6 +2090,15 @@ bool Xdrv39(uint8_t function) } } break; + +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + for (ctr_output = 0; ctr_output < THERMOSTAT_CONTROLLER_OUTPUTS; ctr_output++) { + ThermostatShow(ctr_output); + } + break; +#endif // USE_WEBSERVER + case FUNC_COMMAND: result = DecodeCommand(kThermostatCommands, ThermostatCommand); break; From cba8a5515615ce1f847e116045c677b8d06594c6 Mon Sep 17 00:00:00 2001 From: Charles Date: Sat, 6 Nov 2021 12:39:44 +0100 Subject: [PATCH 006/185] added comments about define strings --- tasmota/xdrv_39_thermostat.ino | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tasmota/xdrv_39_thermostat.ino b/tasmota/xdrv_39_thermostat.ino index 209ecd830..e1a3f21ca 100644 --- a/tasmota/xdrv_39_thermostat.ino +++ b/tasmota/xdrv_39_thermostat.ino @@ -1997,12 +1997,18 @@ void CmndEnableOutputSet(void) * Web UI \*********************************************************************************************/ + +// To be done, add all of this defines in according languages file when all will be finished +// Avoid multiple changes on all language files during developement +// -------------------------------------------------- // xdrv_39_thermostat.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Set Point" #define D_THERMOSTAT_SENSOR "Sensor" #define D_THERMOSTAT_GRADIENT "Gradient" #define D_THERMOSTAT_DUTY_CYCLE "Duty Cycle" +// -------------------------------------------------- + #ifdef USE_WEBSERVER const char HTTP_THERMOSTAT_INFO[] PROGMEM = "{s}" D_THERMOSTAT "{m}%s{e}"; From 08d8fef3c83e7f821badb592300eb071f3b7e4b7 Mon Sep 17 00:00:00 2001 From: kruzer Date: Sat, 6 Nov 2021 23:45:34 +0100 Subject: [PATCH 007/185] Merge settings --- tasmota/settings.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index 45e3671e4..1bb1c51b4 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -736,7 +736,7 @@ typedef struct { uint8_t tcp_config; // F5F uint8_t light_step_pixels; // F60 - uint8_t free_f60[5f]; // F61 - Decrement if adding new Setting variables just above and below + uint8_t free_f60[59]; // F61 - Decrement if adding new Setting variables just above and below // Only 32 bit boundary variables below From 759cc60489fdfa55eb39121995aff7711d02fd4e Mon Sep 17 00:00:00 2001 From: kruzer Date: Sat, 6 Nov 2021 23:48:15 +0100 Subject: [PATCH 008/185] fixed settings --- tasmota/settings.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index 1bb1c51b4..eba5ef88f 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -736,7 +736,7 @@ typedef struct { uint8_t tcp_config; // F5F uint8_t light_step_pixels; // F60 - uint8_t free_f60[59]; // F61 - Decrement if adding new Setting variables just above and below + uint8_t free_f59[59]; // F61 - Decrement if adding new Setting variables just above and below // Only 32 bit boundary variables below From ccd24754d36cd5757c4a92681b600037520f7b56 Mon Sep 17 00:00:00 2001 From: kruzer Date: Sun, 7 Nov 2021 02:40:52 +0100 Subject: [PATCH 009/185] code cleaning --- tasmota/xlgt_01_ws2812.ino | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/tasmota/xlgt_01_ws2812.ino b/tasmota/xlgt_01_ws2812.ino index dd91ebe5d..f47fe531f 100644 --- a/tasmota/xlgt_01_ws2812.ino +++ b/tasmota/xlgt_01_ws2812.ino @@ -462,18 +462,13 @@ void Ws2812Steps(uint32_t schemenr) uint32_t speed = Settings->light_speed; int32_t current_position = Light.strip_timer_counter / speed; - //all is shown already + //all pixels are shown already if(current_position > Settings->light_pixels / Settings->light_step_pixels + scheme_count ) { -// AddLog(LOG_LEVEL_INFO, PSTR("spd:%d cpos:%d tc:%d"), speed,current_position,Light.strip_timer_counter); return; } int32_t colorIndex; - //int32_t leading_step = current_position / Settings->light_step_pixels; int32_t step_nr; - /*if( Light.strip_timer_counter % speed == 0){ - AddLog(LOG_LEVEL_INFO, PSTR("spd:%d cpos:%d lead:%d tc:%d"), speed,current_position,leading_step,Light.strip_timer_counter); - }*/ for (uint32_t i = 0; i < Settings->light_pixels; i++) { step_nr = i / Settings->light_step_pixels; @@ -483,15 +478,6 @@ void Ws2812Steps(uint32_t schemenr) c.R = mcolor[colorIndex].red; c.G = mcolor[colorIndex].green; c.B = mcolor[colorIndex].blue; - if( current_position % 3 == 0){ - //AddLog(LOG_LEVEL_INFO, PSTR("spd:%d cpos:%d lead:%d tc:%d"), speed,current_position,leading_step,Light.strip_timer_counter); - if(i < 15){ - // AddLog(LOG_LEVEL_INFO, PSTR("s_n:%d cidx:%d "), step_nr, colorIndex); - } - } -/* if(i < 2){ - AddLog(LOG_LEVEL_INFO, PSTR("s_n:%d cidx:%d "), step_nr, colorIndex); - }*/ if(Settings->light_rotation & 0x02){ strip->SetPixelColor(Settings->light_pixels - i - 1, c); } else { From ab2438e9a325628ee15ce5ba72dc43d758b677fd Mon Sep 17 00:00:00 2001 From: kruzer Date: Sun, 7 Nov 2021 11:58:46 +0100 Subject: [PATCH 010/185] Added some comments --- tasmota/xlgt_01_ws2812.ino | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tasmota/xlgt_01_ws2812.ino b/tasmota/xlgt_01_ws2812.ino index f47fe531f..e0030dcb8 100644 --- a/tasmota/xlgt_01_ws2812.ino +++ b/tasmota/xlgt_01_ws2812.ino @@ -411,7 +411,8 @@ void Ws2812Steps(uint32_t schemenr) #endif ColorScheme scheme = kSchemes[schemenr]; - if(0==scheme.colors[0].blue && 0==scheme.colors[0].red && 0==scheme.colors[0].green && scheme.count==2){ + // apply main color if current sheme == kStairs + if(scheme.colors == kStairs){ scheme.colors[1].red = Settings->light_color[0]; scheme.colors[1].green = Settings->light_color[1]; scheme.colors[1].blue = Settings->light_color[2]; @@ -432,7 +433,7 @@ void Ws2812Steps(uint32_t schemenr) } if(Settings->light_fade){ - + // generate gradient (width = Width4) for(uint32_t i=1; i < scheme_count - 1; i++){ mcolor[i].red = (uint8_t) wsmap(i, 0, scheme_count, scheme.colors[color_start].red, scheme.colors[color_end].red); mcolor[i].green = (uint8_t) wsmap(i, 0, scheme_count, scheme.colors[color_start].green, scheme.colors[color_end].green); @@ -441,6 +442,7 @@ void Ws2812Steps(uint32_t schemenr) } else { memcpy(mcolor, scheme.colors, sizeof(mcolor)); } + // repair first & last color in gradient; apply scheme rotation if fade==0 mcolor[0].red=scheme.colors[color_start].red; mcolor[0].green=scheme.colors[color_start].green; mcolor[0].blue=scheme.colors[color_start].blue; @@ -449,6 +451,7 @@ void Ws2812Steps(uint32_t schemenr) mcolor[scheme_count-1].blue=scheme.colors[color_end].blue; + // Adjust to dimmer value float dimmer = 100 / (float)Settings->light_dimmer; for (uint32_t i = 0; i < scheme_count; i++) { float fmyRed = (float)mcolor[i].red / dimmer; @@ -462,7 +465,7 @@ void Ws2812Steps(uint32_t schemenr) uint32_t speed = Settings->light_speed; int32_t current_position = Light.strip_timer_counter / speed; - //all pixels are shown already + //all pixels are shown already | rotation change will not change current state if(current_position > Settings->light_pixels / Settings->light_step_pixels + scheme_count ) { return; } @@ -478,6 +481,7 @@ void Ws2812Steps(uint32_t schemenr) c.R = mcolor[colorIndex].red; c.G = mcolor[colorIndex].green; c.B = mcolor[colorIndex].blue; + // Adjust the scheme rotation if(Settings->light_rotation & 0x02){ strip->SetPixelColor(Settings->light_pixels - i - 1, c); } else { From d352277c8edace472c21ca6f73ba06cfc168d2d1 Mon Sep 17 00:00:00 2001 From: Charles Date: Thu, 11 Nov 2021 17:12:58 +0100 Subject: [PATCH 011/185] Fixe compilation error with no DEBUG_THERMOSTAT --- tasmota/xdrv_39_thermostat.ino | 44 +++++++++++++++++----------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/tasmota/xdrv_39_thermostat.ino b/tasmota/xdrv_39_thermostat.ino index a11db79b8..06feb20f8 100644 --- a/tasmota/xdrv_39_thermostat.ino +++ b/tasmota/xdrv_39_thermostat.ino @@ -1253,6 +1253,7 @@ void ThermostatTimerDisarm(uint8_t ctr_output) } #ifdef DEBUG_THERMOSTAT + void ThermostatVirtualSwitch(uint8_t ctr_output) { char domoticz_in_topic[] = DOMOTICZ_IN_TOPIC; @@ -1269,28 +1270,6 @@ void ThermostatVirtualSwitchCtrState(uint8_t ctr_output) MqttPublish(domoticz_in_topic); } -uint8_t ThermostatGetDutyCycle(uint8_t ctr_output) -{ - uint8_t value = 0; - if ( (Thermostat[ctr_output].status.controller_mode == CTR_PI) - || ((Thermostat[ctr_output].status.controller_mode == CTR_HYBRID) - &&(Thermostat[ctr_output].status.phase_hybrid_ctr == CTR_HYBRID_PI))) { - value = Thermostat[ctr_output].time_total_pi / Thermostat[ctr_output].time_pi_cycle; - } - else if ( (Thermostat[ctr_output].status.controller_mode == CTR_RAMP_UP) - || ((Thermostat[ctr_output].status.controller_mode == CTR_HYBRID) - &&(Thermostat[ctr_output].status.phase_hybrid_ctr == CTR_HYBRID_RAMP_UP))) { - if (Thermostat[ctr_output].status.status_output == IFACE_ON) { - value = 100; - } - else { - value = 0; - } - } - return value; -} - - void ThermostatDebug(uint8_t ctr_output) { char result_chr[FLOATSZ]; @@ -1349,6 +1328,27 @@ void ThermostatDebug(uint8_t ctr_output) } #endif // DEBUG_THERMOSTAT +uint8_t ThermostatGetDutyCycle(uint8_t ctr_output) +{ + uint8_t value = 0; + if ( (Thermostat[ctr_output].status.controller_mode == CTR_PI) + || ((Thermostat[ctr_output].status.controller_mode == CTR_HYBRID) + &&(Thermostat[ctr_output].status.phase_hybrid_ctr == CTR_HYBRID_PI))) { + value = Thermostat[ctr_output].time_total_pi / Thermostat[ctr_output].time_pi_cycle; + } + else if ( (Thermostat[ctr_output].status.controller_mode == CTR_RAMP_UP) + || ((Thermostat[ctr_output].status.controller_mode == CTR_HYBRID) + &&(Thermostat[ctr_output].status.phase_hybrid_ctr == CTR_HYBRID_RAMP_UP))) { + if (Thermostat[ctr_output].status.status_output == IFACE_ON) { + value = 100; + } + else { + value = 0; + } + } + return value; +} + void ThermostatGetLocalSensor(uint8_t ctr_output) { String buf = ResponseData(); // copy the string into a new buffer that will be modified JsonParser parser((char*)buf.c_str()); From 967d231f388c76f33a13f2058ee5eb060b811c93 Mon Sep 17 00:00:00 2001 From: Charles Date: Thu, 11 Nov 2021 17:34:51 +0100 Subject: [PATCH 012/185] Display Current Temperature instead of Sensor Temperature --- tasmota/xdrv_39_thermostat.ino | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tasmota/xdrv_39_thermostat.ino b/tasmota/xdrv_39_thermostat.ino index 06feb20f8..f1258abee 100644 --- a/tasmota/xdrv_39_thermostat.ino +++ b/tasmota/xdrv_39_thermostat.ino @@ -2004,7 +2004,7 @@ void CmndEnableOutputSet(void) // xdrv_39_thermostat.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Set Point" -#define D_THERMOSTAT_SENSOR "Sensor" +#define D_THERMOSTAT_SENSOR "Current" #define D_THERMOSTAT_GRADIENT "Gradient" #define D_THERMOSTAT_DUTY_CYCLE "Duty Cycle" // -------------------------------------------------- @@ -2045,7 +2045,6 @@ void ThermostatShow(uint8_t ctr_output) WSContentSend_P(HTTP_THERMOSTAT_DUTY_CYCLE, ThermostatGetDutyCycle(ctr_output) ); } - #endif // USE_WEBSERVER } From d98235def3101aecfdbbdc41140984f3071dd642 Mon Sep 17 00:00:00 2001 From: Charles Date: Thu, 11 Nov 2021 19:54:00 +0100 Subject: [PATCH 013/185] added cycle time and Pi auto tuning on WEBUI --- tasmota/xdrv_39_thermostat.ino | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tasmota/xdrv_39_thermostat.ino b/tasmota/xdrv_39_thermostat.ino index f1258abee..60a8c7b10 100644 --- a/tasmota/xdrv_39_thermostat.ino +++ b/tasmota/xdrv_39_thermostat.ino @@ -2006,7 +2006,9 @@ void CmndEnableOutputSet(void) #define D_THERMOSTAT_SET_POINT "Set Point" #define D_THERMOSTAT_SENSOR "Current" #define D_THERMOSTAT_GRADIENT "Gradient" -#define D_THERMOSTAT_DUTY_CYCLE "Duty Cycle" +#define D_THERMOSTAT_DUTY_CYCLE "Duty cycle" +#define D_THERMOSTAT_CYCLE_TIME "Cycle time" +#define D_THERMOSTAT_PI_AUTOTUNE "PI Auto tuning" // -------------------------------------------------- @@ -2014,6 +2016,9 @@ void CmndEnableOutputSet(void) const char HTTP_THERMOSTAT_INFO[] PROGMEM = "{s}" D_THERMOSTAT "{m}%s{e}"; const char HTTP_THERMOSTAT_TEMPERATURE[] PROGMEM = "{s}%s " D_TEMPERATURE "{m}%*_f " D_UNIT_DEGREE "%c{e}"; const char HTTP_THERMOSTAT_DUTY_CYCLE[] PROGMEM = "{s}" D_THERMOSTAT_DUTY_CYCLE "{m}%d " D_UNIT_PERCENT "{e}"; +const char HTTP_THERMOSTAT_CYCLE_TIME[] PROGMEM = "{s}" D_THERMOSTAT_CYCLE_TIME "{m}%d " D_UNIT_MINUTE "{e}"; +const char HTTP_THERMOSTAT_PI_AUTOTUNE[] PROGMEM = "{s}" D_THERMOSTAT_PI_AUTOTUNE "{m}%s{e}"; +const char HTTP_THERMOSTAT_HL[] PROGMEM = "{s}
{m}
{e}"; #endif // USE_WEBSERVER @@ -2021,6 +2026,8 @@ void ThermostatShow(uint8_t ctr_output) { #ifdef USE_WEBSERVER + WSContentSend_P(HTTP_THERMOSTAT_HL); + if (Thermostat[ctr_output].status.thermostat_mode == THERMOSTAT_OFF) { WSContentSend_P(HTTP_THERMOSTAT_INFO, D_DISABLED ); @@ -2043,6 +2050,14 @@ void ThermostatShow(uint8_t ctr_output) f_temperature = value / 1000.0f; WSContentSend_PD(HTTP_THERMOSTAT_TEMPERATURE, D_THERMOSTAT_GRADIENT, Settings->flag2.temperature_resolution, &f_temperature, c_unit); WSContentSend_P(HTTP_THERMOSTAT_DUTY_CYCLE, ThermostatGetDutyCycle(ctr_output) ); + WSContentSend_P(HTTP_THERMOSTAT_CYCLE_TIME, Thermostat[ctr_output].time_pi_cycle ); + + #ifdef USE_PI_AUTOTUNING + WSContentSend_P(HTTP_THERMOSTAT_PI_AUTOTUNE, D_ENABLED ); + #else + WSContentSend_P(HTTP_THERMOSTAT_PI_AUTOTUNE, D_DISABLED ); + #endif + } #endif // USE_WEBSERVER From 437c72cfa9050f3457aa97df6788be0e2bd2e32c Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Fri, 12 Nov 2021 09:13:01 +0100 Subject: [PATCH 014/185] Fix compiler warning --- tasmota/support.ino | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tasmota/support.ino b/tasmota/support.ino index 1bc0ba4a3..54f95bc28 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -1841,16 +1841,14 @@ int8_t ParseSerialConfig(const char *pstr) } #ifdef ESP8266 -SerConfu8 ConvertSerialConfigESP8286(uint8_t serial_config) { +SerConfu8 ConvertSerialConfig(uint8_t serial_config) { return (SerConfu8)pgm_read_byte(kTasmotaSerialConfig + serial_config); } -#define ConvertSerialConfig(a) ConvertSerialConfigESP8286(a) #endif // ESP8266 #ifdef ESP32 -uint32_t ConvertSerialConfigESP32(uint8_t serial_config) { +uint32_t ConvertSerialConfig(uint8_t serial_config) { return (uint32_t)pgm_read_dword(kTasmotaSerialConfig + serial_config); } -#define ConvertSerialConfig(a) ConvertSerialConfigESP32(a) #endif // ESP32 // workaround disabled 05.11.2021 solved with https://github.com/espressif/arduino-esp32/pull/5549 From c52f130afb4495f5f50f72ccd4162e62d85fd069 Mon Sep 17 00:00:00 2001 From: David Gwynne Date: Sat, 13 Nov 2021 20:37:10 +1000 Subject: [PATCH 015/185] apply IKEA tradfri quick to symfonisk too --- tasmota/xdrv_23_zigbee_5_converters.ino | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index 494d26fb8..f2d3334eb 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -1311,8 +1311,9 @@ void ZCLFrame::computeSyntheticAttributes(Z_attribute_list& attr_list) { } break; case 0x00010021: // BatteryPercentage - if (modelId.startsWith(F("TRADFRI"))) { - attr.setUInt(attr.getUInt() * 2); // bug in TRADFRI battery, need to double the value + if (modelId.startsWith(F("TRADFRI")) || + modelId.startsWith(F("SYMFONISK"))) { + attr.setUInt(attr.getUInt() * 2); // bug in IKEA remotes battery, need to double the value } break; case 0x00060000: // "Power" for lumi Door/Window is converted to "Contact" From f19462f64bf6c910201cb96cf2a6d3aa4d0e2377 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 13 Nov 2021 12:44:45 +0100 Subject: [PATCH 016/185] Fix ESP32-S2 TSettings memory usage Fix ESP32-S2 TSettings memory usage fixed to 4096 bytes regression from v9.5.0.8 --- CHANGELOG.md | 3 +++ RELEASENOTES.md | 1 + tasmota/settings.h | 18 +++++++++--------- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cd72e5052..14efd97f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ All notable changes to this project will be documented in this file. ### Added - Support for HDC2010 temperature/humidity sensor by Luc Boudreau (#13633) +### Breaking Changed +- ESP32-S2 TSettings memory usage fixed to 4096 bytes regression from v9.5.0.8 + ### Changed - ESP32 core library from v1.0.7.5 to v2.0.1 diff --git a/RELEASENOTES.md b/RELEASENOTES.md index af4c13ba3..c0e1f5ff4 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -108,6 +108,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo - Support for HDC2010 temperature/humidity sensor by Luc Boudreau [#13633](https://github.com/arendst/Tasmota/issues/13633) ### Breaking Changed +- ESP32-S2 TSettings memory usage fixed to 4096 bytes regression from v9.5.0.8 ### Changed - File editor no-wrap [#13427](https://github.com/arendst/Tasmota/issues/13427) diff --git a/tasmota/settings.h b/tasmota/settings.h index 419313774..0cde278e9 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -524,7 +524,7 @@ typedef struct { uint8_t ex_switchmode[8]; // 3A4 - Free since 9.2.0.6 - myio my_gp; // 3AC 2 x 18 bytes (ESP8266) / 2 x 40 bytes (ESP32) / 2 x 22 bytes (ESP32-C3) + myio my_gp; // 3AC 2x18 bytes (ESP8266) / 2x40 bytes (ESP32) / 2x22 bytes (ESP32-C3) / 2x47 bytes (ESP32-S2) #ifdef ESP8266 uint16_t gpio16_converted; // 3D0 uint8_t free_esp8266_3D2[42]; // 3D2 @@ -534,7 +534,7 @@ typedef struct { uint8_t free_esp32c3_3D8[36]; // 3D8 - Due to smaller myio #endif // CONFIG_IDF_TARGET_ESP32C3 #endif // ESP32 - mytmplt user_template; // 3FC 2 x 15 bytes (ESP8266) / 2 x 37 bytes (ESP32) / 2 x 23 bytes (ESP32-C3) + mytmplt user_template; // 3FC 2x15 bytes (ESP8266) / 2x37 bytes (ESP32) / 2x23 bytes (ESP32-C3) / 2x37 bytes (ESP32-S2) #ifdef ESP8266 uint8_t free_esp8266_41A[55]; // 41A #endif // ESP8266 @@ -546,6 +546,9 @@ typedef struct { uint8_t eth_clk_mode; // 447 uint8_t free_esp32_448[4]; // 448 +#ifdef CONFIG_IDF_TARGET_ESP32S2 + uint8_t free_esp32s2_456[2]; // 456 - fix 32-bit offset for WebCamCfg +#endif WebCamCfg webcam_config; // 44C uint8_t eth_address; // 450 @@ -563,9 +566,11 @@ typedef struct { myio8 ex_my_gp8; // 484 17 bytes (ESP8266) - Free since 9.0.0.1 #endif // ESP8266 #ifdef ESP32 - +#ifdef CONFIG_IDF_TARGET_ESP32S2 + uint8_t free_esp32s2_494[1]; // 494 - 2 bytes extra because of WebCamCfg 32-bit offset +#else uint8_t free_esp32_484[17]; // 484 - +#endif #endif // ESP32 uint8_t ex_my_adc0; // 495 Free since 9.0.0.1 @@ -634,9 +639,7 @@ typedef struct { mytmplt8285 ex_user_template8; // 72F 14 bytes (ESP8266) - Free since 9.0.0.1 #endif // ESP8266 #ifdef ESP32 - uint8_t free_esp32_72f[14]; // 72F - #endif // ESP32 uint8_t novasds_startingoffset; // 73D @@ -763,10 +766,7 @@ typedef struct { uint32_t cfg_crc32; // FFC } TSettings; -#ifndef CONFIG_IDF_TARGET_ESP32S2 -// For the ESP32-S2 the settings area has been made larger than 4096 by accident in order to support more GPIO's static_assert(sizeof(TSettings) == 4096, "TSettings Size is not correct"); -#endif typedef struct { uint16_t valid; // 280 (RTC memory offset 100 - sizeof(RTCRBT)) From 02346b4e49290f54713904a5c7c92da8d4bb3c26 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 13 Nov 2021 12:49:38 +0100 Subject: [PATCH 017/185] Update comments --- tasmota/tasmota_template.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index 0de887e9c..4f9b41b4b 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -1076,11 +1076,11 @@ const char PINS_WEMOS[] PROGMEM = "IOTXIORXIOIOFLFLFLFLFLFLIOIOIOIOIOIOIOIOIOIOI typedef struct MYIO { uint16_t io[MAX_GPIO_PIN]; -} myio; // ESP8266: 18 * 2 = 36 bytes / ESP32: 40 * 2 = 80 bytes / ESP32-C3: 22 * 2 = 44 bytes +} myio; // ESP8266: 18*2 = 36 bytes / ESP32: 40*2 = 80 bytes / ESP32-C3: 22*2 = 44 bytes / ESP32-S2: 47*2 = 94 bytes typedef struct MYCFGIO { uint16_t io[MAX_USER_PINS]; -} mycfgio; // ESP8266: 14 * 2 = 28 bytes / ESP32: 36 * 2 = 72 bytes / ESP32-C3: 22 * 2 = 44 bytes +} mycfgio; // ESP8266: 14*2 = 28 bytes / ESP32: 36*2 = 72 bytes / ESP32-C3: 22*2 = 44 bytes / ESP32-S2: 36*2 = 72 bytes #define GPIO_FLAG_USED 0 // Currently no flags used @@ -1107,9 +1107,9 @@ typedef union { } gpio_flag; // 2 bytes typedef struct MYTMPLT { - mycfgio gp; // 28 / 72 / 44 bytes + mycfgio gp; // 28 / 72 / 44 / 72 bytes gpio_flag flag; // 2 bytes -} mytmplt; // 30 / 74 / 46 bytes +} mytmplt; // 30 / 74 / 46 / 74 bytes //******************************************************************************************** From 1e326460bde34fe432517a5dcaf4e05fe562a4da Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 13 Nov 2021 14:38:21 +0100 Subject: [PATCH 018/185] ESP8266 Gratuitous ARP enabled - ESP8266 Gratuitous ARP enabled and set to 60 seconds (#13623) - Version bump to 10.0.0.3 --- CHANGELOG.md | 6 +++++- RELEASENOTES.md | 7 ++++--- tasmota/my_user_config.h | 2 +- tasmota/settings.ino | 5 +++++ tasmota/tasmota_version.h | 2 +- 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 14efd97f8..73594ea8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,11 @@ All notable changes to this project will be documented in this file. ## [Unreleased] - Development -## [10.0.0.2] +## [10.0.0.3] +### Changed +- ESP8266 Gratuitous ARP enabled and set to 60 seconds (#13623) + +## [10.0.0.2] 20211113 ### Added - Support for HDC2010 temperature/humidity sensor by Luc Boudreau (#13633) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index c0e1f5ff4..858ab7ac7 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -100,7 +100,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo [Complete list](BUILDS.md) of available feature and sensors. -## Changelog v10.0.0.2 +## Changelog v10.0.0.3 ### Added - 1 second heartbeat GPIO - ESP32 Berry add module ``python_compat`` to be closer to Python syntax [#13428](https://github.com/arendst/Tasmota/issues/13428) @@ -111,9 +111,10 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo - ESP32-S2 TSettings memory usage fixed to 4096 bytes regression from v9.5.0.8 ### Changed -- File editor no-wrap [#13427](https://github.com/arendst/Tasmota/issues/13427) - ESP32 core library from v1.0.7.4 to v2.0.1 -- ESP32-C3 core library from v2.0.0-post to v2.0.1-rc1 +- ESP32-C3 core library from v2.0.0-post to v2.0.1 +- File editor no-wrap [#13427](https://github.com/arendst/Tasmota/issues/13427) +- ESP8266 Gratuitous ARP enabled and set to 60 seconds [#13623](https://github.com/arendst/Tasmota/issues/13623) ### Fixed - Initial reset RTC memory based variables like EnergyToday and EnergyTotal diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 6f708f58b..432532e6e 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -79,7 +79,7 @@ #define WIFI_CONFIG_TOOL WIFI_RETRY // [WifiConfig] Default tool if Wi-Fi fails to connect (default option: 4 - WIFI_RETRY) // (WIFI_RESTART, WIFI_MANAGER, WIFI_RETRY, WIFI_WAIT, WIFI_SERIAL, WIFI_MANAGER_RESET_ONLY) // The configuration can be changed after first setup using WifiConfig 0, 2, 4, 5, 6 and 7. -#define WIFI_ARP_INTERVAL 0 // [SetOption41] Send gratuitous ARP interval +#define WIFI_ARP_INTERVAL 60 // [SetOption41] Send gratuitous ARP interval #define WIFI_SCAN_AT_RESTART false // [SetOption56] Scan Wi-Fi network at restart for configured AP's #define WIFI_SCAN_REGULARLY true // [SetOption57] Scan Wi-Fi network every 44 minutes for configured AP's diff --git a/tasmota/settings.ino b/tasmota/settings.ino index e64e0cec1..ec09129f4 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -1454,6 +1454,11 @@ void SettingsDelta(void) { memset(&Settings->energy_kWhtoday_ph, 0, 36); memset(&RtcSettings.energy_kWhtoday_ph, 0, 24); } + if (Settings->version < 0x0A000003) { + if (0 == Settings->param[P_ARP_GRATUITOUS]) { + Settings->param[P_ARP_GRATUITOUS] = WIFI_ARP_INTERVAL; + } + } Settings->version = VERSION; SettingsSave(1); diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index 5c33aeeaf..7e3e74d42 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,6 +20,6 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x0A000002; +const uint32_t VERSION = 0x0A000003; #endif // _TASMOTA_VERSION_H_ From fa06a7bcfc25c2ba30b79e13d66995bd55bccece Mon Sep 17 00:00:00 2001 From: stefanbode Date: Sat, 13 Nov 2021 17:31:04 +0100 Subject: [PATCH 019/185] Bugfix: Shutter missed stop on tilt Fix bug where shutter continuously moves, when tilt end was not reached due to rounding effects. --- tasmota/xdrv_27_shutter.ino | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 0e1e1e23a..52fba66ff 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -631,8 +631,12 @@ int32_t ShutterCalculatePosition(uint32_t i) case SHT_TIME: case SHT_TIME_UP_DOWN: case SHT_TIME_GARAGE: - if (Shutter[i].time <= Shutter[i].venetian_delay && Shutter[i].tilt_config[2] > 0) { - Shutter[i].tilt_real_pos = (Shutter[i].tilt_start_pos + ((Shutter[i].direction * (int16_t)Shutter[i].time * (Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0])) / Shutter[i].tilt_config[2])); + if (Shutter[i].tilt_config[2] > 0) { + if (Shutter[i].time <= Shutter[i].venetian_delay) { + Shutter[i].tilt_real_pos = (Shutter[i].tilt_start_pos + ((Shutter[i].direction * (int16_t)Shutter[i].time * (Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0])) / Shutter[i].tilt_config[2])); + } else { + Shutter[i].tilt_real_pos = Shutter[i].direction == 1 ? Shutter[i].tilt_config[1] : Shutter[i].tilt_config[0]; + } } return Shutter[i].start_position + ( (Shutter[i].time - tmin(Shutter[i].venetian_delay+Shutter[i].motordelay, Shutter[i].time)) * (Shutter[i].direction > 0 ? RESOLUTION : -Shutter[i].close_velocity)); break; From a9f058542953484405c2efa3323f4350c6f479e0 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sat, 13 Nov 2021 20:45:27 +0100 Subject: [PATCH 020/185] Autoconf v1 (#13665) * Fix compiler warning * Autoconfiguration for ESP32 and variants --- CHANGELOG.md | 3 + lib/libesp32/Berry/default/be_autoconf_lib.c | 1389 +++++++++++++++++ lib/libesp32/Berry/default/be_display_lib.c | 29 + lib/libesp32/Berry/default/be_modtab.c | 8 + lib/libesp32/Berry/default/be_tasmotalib.c | 244 +-- .../Berry/default/embedded/Tasmota.be | 45 +- .../Berry/default/embedded/autoconf.be | 387 +++++ lib/libesp32/Berry/generate/be_const_strtab.h | 649 ++++---- .../Berry/generate/be_const_strtab_def.h | 979 ++++++------ .../generate/be_fixed_be_class_tasmota.h | 149 +- lib/libesp32/Berry/generate/be_fixed_string.h | 18 +- lib/libesp32/Berry/src/be_solidifylib.c | 10 +- lib/libesp32/Berry/src/be_strlib.c | 51 + .../Zip-readonly-FS/src/ZipReadFS.cpp | 2 +- tasmota/my_user_config.h | 14 + tasmota/xdrv_13_display.ino | 4 +- tasmota/xdrv_52_0_berry_struct.ino | 1 + tasmota/xdrv_52_3_berry_display.ino | 63 + tasmota/xdrv_52_7_berry_embedded.ino | 5 + tasmota/xdrv_52_9_berry.ino | 34 + tasmota/xdrv_54_lvgl.ino | 5 +- tasmota/xdsp_08_ILI9488_UD.ino | 2 +- tasmota/xdsp_17_universal.ino | 2 +- 23 files changed, 3071 insertions(+), 1022 deletions(-) create mode 100644 lib/libesp32/Berry/default/be_autoconf_lib.c create mode 100644 lib/libesp32/Berry/default/be_display_lib.c create mode 100644 lib/libesp32/Berry/default/embedded/autoconf.be create mode 100644 tasmota/xdrv_52_3_berry_display.ino diff --git a/CHANGELOG.md b/CHANGELOG.md index 73594ea8f..cf3b47477 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file. ## [Unreleased] - Development ## [10.0.0.3] +### Added +- Autoconfiguration for ESP32 and variants + ### Changed - ESP8266 Gratuitous ARP enabled and set to 60 seconds (#13623) diff --git a/lib/libesp32/Berry/default/be_autoconf_lib.c b/lib/libesp32/Berry/default/be_autoconf_lib.c new file mode 100644 index 000000000..bec1382ea --- /dev/null +++ b/lib/libesp32/Berry/default/be_autoconf_lib.c @@ -0,0 +1,1389 @@ +/******************************************************************** + * Tasmota lib + * + * To use: `import autoconf` + * + *******************************************************************/ +#include "be_constobj.h" + + +/******************************************************************** +** Solidified function: page_autoconf_ctl +********************************************************************/ +be_local_closure(page_autoconf_ctl, /* name */ + be_nested_proto( + 13, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[41]) { /* constants */ + /* K0 */ be_nested_string("webserver", 1572454038, 9), + /* K1 */ be_nested_string("string", 398550328, 6), + /* K2 */ be_nested_string("path", -2071507658, 4), + /* K3 */ be_nested_string("check_privileged_access", -602033328, 23), + /* K4 */ be_nested_string("has_arg", 424878688, 7), + /* K5 */ be_nested_string("reapply", -516027964, 7), + /* K6 */ be_nested_string("tasmota", 424643812, 7), + /* K7 */ be_nested_string("log", 1062293841, 3), + /* K8 */ be_nested_string("CFG: removing first time marker", 2125556683, 31), + /* K9 */ be_const_int(2), + /* K10 */ be_nested_string("clear_first_time", 632769909, 16), + /* K11 */ be_nested_string("redirect", 389758641, 8), + /* K12 */ be_nested_string("/?rst=", 580074707, 6), + /* K13 */ be_nested_string("zip", -1417514060, 3), + /* K14 */ be_nested_string("CFG: removing autoconf files", -280262326, 28), + /* K15 */ be_nested_string("delete_all_configs", -1912899718, 18), + /* K16 */ be_nested_string("arg", 1047474471, 3), + /* K17 */ be_nested_string("reset", 1695364032, 5), + /* K18 */ be_nested_string("format", -1180859054, 6), + /* K19 */ be_nested_string("https://raw.githubusercontent.com/tasmota/autoconf/main/%s/%s_autoconf.zip", 2084253523, 74), + /* K20 */ be_nested_string("arch", -1342162999, 4), + /* K21 */ be_nested_string("CFG: downloading '%s'", 589480701, 21), + /* K22 */ be_nested_string("%s_autoconf.zip", -1148460718, 15), + /* K23 */ be_nested_string("webclient", -218578150, 9), + /* K24 */ be_nested_string("begin", 1748273790, 5), + /* K25 */ be_nested_string("GET", -1763262857, 3), + /* K26 */ be_nested_string("return code=%i", 2127454401, 14), + /* K27 */ be_nested_string("connection_error", 1358926260, 16), + /* K28 */ be_nested_string("write_file", -1117308417, 10), + /* K29 */ be_nested_string("close", 667630371, 5), + /* K30 */ be_nested_string("value_error", 773297791, 11), + /* K31 */ be_nested_string("Unknown command", 1830905432, 15), + /* K32 */ be_nested_string("CFG: Exception> '%s' - %s", 1228874553, 25), + /* K33 */ be_nested_string("content_start", -1357458227, 13), + /* K34 */ be_nested_string("Parameter error", -454925258, 15), + /* K35 */ be_nested_string("content_send_style", 1087907647, 18), + /* K36 */ be_nested_string("content_send", 1673733649, 12), + /* K37 */ be_nested_string("

Exception:
'%s'
%s

", -42402214, 59), + /* K38 */ be_nested_string("content_button", 1956476087, 14), + /* K39 */ be_nested_string("BUTTON_CONFIGURATION", 70820856, 20), + /* K40 */ be_nested_string("content_stop", 658554751, 12), + }), + (be_nested_const_str("page_autoconf_ctl", -1841585800, 17)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[117]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0xA40A0200, // 0001 IMPORT R2 K1 + 0xA40E0400, // 0002 IMPORT R3 K2 + 0x8C100303, // 0003 GETMET R4 R1 K3 + 0x7C100200, // 0004 CALL R4 1 + 0x74120001, // 0005 JMPT R4 #0008 + 0x4C100000, // 0006 LDNIL R4 + 0x80040800, // 0007 RET 1 R4 + 0xA802004E, // 0008 EXBLK 0 #0058 + 0x8C100304, // 0009 GETMET R4 R1 K4 + 0x58180005, // 000A LDCONST R6 K5 + 0x7C100400, // 000B CALL R4 2 + 0x7812000A, // 000C JMPF R4 #0018 + 0xB8120C00, // 000D GETNGBL R4 K6 + 0x8C100907, // 000E GETMET R4 R4 K7 + 0x58180008, // 000F LDCONST R6 K8 + 0x581C0009, // 0010 LDCONST R7 K9 + 0x7C100600, // 0011 CALL R4 3 + 0x8C10010A, // 0012 GETMET R4 R0 K10 + 0x7C100200, // 0013 CALL R4 1 + 0x8C10030B, // 0014 GETMET R4 R1 K11 + 0x5818000C, // 0015 LDCONST R6 K12 + 0x7C100400, // 0016 CALL R4 2 + 0x7002003D, // 0017 JMP #0056 + 0x8C100304, // 0018 GETMET R4 R1 K4 + 0x5818000D, // 0019 LDCONST R6 K13 + 0x7C100400, // 001A CALL R4 2 + 0x78120038, // 001B JMPF R4 #0055 + 0xB8120C00, // 001C GETNGBL R4 K6 + 0x8C100907, // 001D GETMET R4 R4 K7 + 0x5818000E, // 001E LDCONST R6 K14 + 0x581C0009, // 001F LDCONST R7 K9 + 0x7C100600, // 0020 CALL R4 3 + 0x8C10010F, // 0021 GETMET R4 R0 K15 + 0x7C100200, // 0022 CALL R4 1 + 0x8C100310, // 0023 GETMET R4 R1 K16 + 0x5818000D, // 0024 LDCONST R6 K13 + 0x7C100400, // 0025 CALL R4 2 + 0x20140911, // 0026 NE R5 R4 K17 + 0x78160026, // 0027 JMPF R5 #004F + 0x8C140512, // 0028 GETMET R5 R2 K18 + 0x581C0013, // 0029 LDCONST R7 K19 + 0xB8220C00, // 002A GETNGBL R8 K6 + 0x8C201114, // 002B GETMET R8 R8 K20 + 0x7C200200, // 002C CALL R8 1 + 0x5C240800, // 002D MOVE R9 R4 + 0x7C140800, // 002E CALL R5 4 + 0xB81A0C00, // 002F GETNGBL R6 K6 + 0x8C180D07, // 0030 GETMET R6 R6 K7 + 0x8C200512, // 0031 GETMET R8 R2 K18 + 0x58280015, // 0032 LDCONST R10 K21 + 0x5C2C0A00, // 0033 MOVE R11 R5 + 0x7C200600, // 0034 CALL R8 3 + 0x58240009, // 0035 LDCONST R9 K9 + 0x7C180600, // 0036 CALL R6 3 + 0x8C180512, // 0037 GETMET R6 R2 K18 + 0x58200016, // 0038 LDCONST R8 K22 + 0x5C240800, // 0039 MOVE R9 R4 + 0x7C180600, // 003A CALL R6 3 + 0xB81E2E00, // 003B GETNGBL R7 K23 + 0x7C1C0000, // 003C CALL R7 0 + 0x8C200F18, // 003D GETMET R8 R7 K24 + 0x5C280A00, // 003E MOVE R10 R5 + 0x7C200400, // 003F CALL R8 2 + 0x8C200F19, // 0040 GETMET R8 R7 K25 + 0x7C200200, // 0041 CALL R8 1 + 0x542600C7, // 0042 LDINT R9 200 + 0x20241009, // 0043 NE R9 R8 R9 + 0x78260004, // 0044 JMPF R9 #004A + 0x8C240512, // 0045 GETMET R9 R2 K18 + 0x582C001A, // 0046 LDCONST R11 K26 + 0x5C301000, // 0047 MOVE R12 R8 + 0x7C240600, // 0048 CALL R9 3 + 0xB0063609, // 0049 RAISE 1 K27 R9 + 0x8C240F1C, // 004A GETMET R9 R7 K28 + 0x5C2C0C00, // 004B MOVE R11 R6 + 0x7C240400, // 004C CALL R9 2 + 0x8C240F1D, // 004D GETMET R9 R7 K29 + 0x7C240200, // 004E CALL R9 1 + 0x8C14010A, // 004F GETMET R5 R0 K10 + 0x7C140200, // 0050 CALL R5 1 + 0x8C14030B, // 0051 GETMET R5 R1 K11 + 0x581C000C, // 0052 LDCONST R7 K12 + 0x7C140400, // 0053 CALL R5 2 + 0x70020000, // 0054 JMP #0056 + 0xB0063D1F, // 0055 RAISE 1 K30 K31 + 0xA8040001, // 0056 EXBLK 1 1 + 0x7002001B, // 0057 JMP #0074 + 0xAC100002, // 0058 CATCH R4 0 2 + 0x70020018, // 0059 JMP #0073 + 0x60180001, // 005A GETGBL R6 G1 + 0x8C1C0512, // 005B GETMET R7 R2 K18 + 0x58240020, // 005C LDCONST R9 K32 + 0x5C280800, // 005D MOVE R10 R4 + 0x5C2C0A00, // 005E MOVE R11 R5 + 0x7C1C0800, // 005F CALL R7 4 + 0x7C180200, // 0060 CALL R6 1 + 0x8C180321, // 0061 GETMET R6 R1 K33 + 0x58200022, // 0062 LDCONST R8 K34 + 0x7C180400, // 0063 CALL R6 2 + 0x8C180323, // 0064 GETMET R6 R1 K35 + 0x7C180200, // 0065 CALL R6 1 + 0x8C180324, // 0066 GETMET R6 R1 K36 + 0x8C200512, // 0067 GETMET R8 R2 K18 + 0x58280025, // 0068 LDCONST R10 K37 + 0x5C2C0800, // 0069 MOVE R11 R4 + 0x5C300A00, // 006A MOVE R12 R5 + 0x7C200800, // 006B CALL R8 4 + 0x7C180400, // 006C CALL R6 2 + 0x8C180326, // 006D GETMET R6 R1 K38 + 0x88200327, // 006E GETMBR R8 R1 K39 + 0x7C180400, // 006F CALL R6 2 + 0x8C180328, // 0070 GETMET R6 R1 K40 + 0x7C180200, // 0071 CALL R6 1 + 0x70020000, // 0072 JMP #0074 + 0xB0080000, // 0073 RAISE 2 R0 R0 + 0x80000000, // 0074 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: autoexec +********************************************************************/ +be_local_closure(autoexec, /* name */ + be_nested_proto( + 9, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[32]) { /* constants */ + /* K0 */ be_nested_string("_archive", -290407892, 8), + /* K1 */ be_nested_string("path", -2071507658, 4), + /* K2 */ be_nested_string("#init.bat", -997372219, 9), + /* K3 */ be_nested_string("is_first_time", 275242384, 13), + /* K4 */ be_nested_string("exists", 1002329533, 6), + /* K5 */ be_nested_string("set_first_time", -1183719746, 14), + /* K6 */ be_nested_string("run_bat", -1758063998, 7), + /* K7 */ be_nested_string("tasmota", 424643812, 7), + /* K8 */ be_nested_string("log", 1062293841, 3), + /* K9 */ be_nested_string("CFG: 'init.bat' done, restarting", 1569670677, 32), + /* K10 */ be_const_int(2), + /* K11 */ be_nested_string("cmd", -158181397, 3), + /* K12 */ be_nested_string("Restart 1", -790511441, 9), + /* K13 */ be_nested_string("#display.ini", 182218220, 12), + /* K14 */ be_nested_string("gpio", -1656812038, 4), + /* K15 */ be_nested_string("pin_used", -261112684, 8), + /* K16 */ be_nested_string("OPTION_A", 1133299440, 8), + /* K17 */ be_nested_string("display.ini", -1648793295, 11), + /* K18 */ be_nested_string("CFG: skipping 'display.ini' because already present in file-system", -329418032, 66), + /* K19 */ be_nested_string("display", 1164572437, 7), + /* K20 */ be_nested_string("r", -150190315, 1), + /* K21 */ be_nested_string("read", -824204347, 4), + /* K22 */ be_nested_string("close", 667630371, 5), + /* K23 */ be_nested_string("start", 1697318111, 5), + /* K24 */ be_nested_string("#autoexec.bat", -912076799, 13), + /* K25 */ be_nested_string("CFG: running ", -1816632762, 13), + /* K26 */ be_const_int(3), + /* K27 */ be_nested_string("CFG: ran ", -715396824, 10), + /* K28 */ be_nested_string("#autoexec.be", 1181757091, 12), + /* K29 */ be_nested_string("CFG: loading ", -284605793, 13), + /* K30 */ be_nested_string("load", -435725847, 4), + /* K31 */ be_nested_string("CFG: loaded ", -584693758, 13), + }), + (be_nested_const_str("autoexec", -618105405, 8)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[107]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x4C080000, // 0001 LDNIL R2 + 0x1C040202, // 0002 EQ R1 R1 R2 + 0x78060000, // 0003 JMPF R1 #0005 + 0x80000200, // 0004 RET 0 + 0xA4060200, // 0005 IMPORT R1 K1 + 0x88080100, // 0006 GETMBR R2 R0 K0 + 0x00080502, // 0007 ADD R2 R2 K2 + 0x8C0C0103, // 0008 GETMET R3 R0 K3 + 0x7C0C0200, // 0009 CALL R3 1 + 0x780E0012, // 000A JMPF R3 #001E + 0x8C0C0304, // 000B GETMET R3 R1 K4 + 0x5C140400, // 000C MOVE R5 R2 + 0x7C0C0400, // 000D CALL R3 2 + 0x780E000E, // 000E JMPF R3 #001E + 0x8C0C0105, // 000F GETMET R3 R0 K5 + 0x7C0C0200, // 0010 CALL R3 1 + 0x8C0C0106, // 0011 GETMET R3 R0 K6 + 0x5C140400, // 0012 MOVE R5 R2 + 0x7C0C0400, // 0013 CALL R3 2 + 0xB80E0E00, // 0014 GETNGBL R3 K7 + 0x8C0C0708, // 0015 GETMET R3 R3 K8 + 0x58140009, // 0016 LDCONST R5 K9 + 0x5818000A, // 0017 LDCONST R6 K10 + 0x7C0C0600, // 0018 CALL R3 3 + 0xB80E0E00, // 0019 GETNGBL R3 K7 + 0x8C0C070B, // 001A GETMET R3 R3 K11 + 0x5814000C, // 001B LDCONST R5 K12 + 0x7C0C0400, // 001C CALL R3 2 + 0x80000600, // 001D RET 0 + 0x880C0100, // 001E GETMBR R3 R0 K0 + 0x000C070D, // 001F ADD R3 R3 K13 + 0x5C080600, // 0020 MOVE R2 R3 + 0xB80E1C00, // 0021 GETNGBL R3 K14 + 0x8C0C070F, // 0022 GETMET R3 R3 K15 + 0xB8161C00, // 0023 GETNGBL R5 K14 + 0x88140B10, // 0024 GETMBR R5 R5 K16 + 0x5818000A, // 0025 LDCONST R6 K10 + 0x7C0C0600, // 0026 CALL R3 3 + 0x780E0019, // 0027 JMPF R3 #0042 + 0x8C0C0304, // 0028 GETMET R3 R1 K4 + 0x5C140400, // 0029 MOVE R5 R2 + 0x7C0C0400, // 002A CALL R3 2 + 0x780E0015, // 002B JMPF R3 #0042 + 0x8C0C0304, // 002C GETMET R3 R1 K4 + 0x58140011, // 002D LDCONST R5 K17 + 0x7C0C0400, // 002E CALL R3 2 + 0x780E0005, // 002F JMPF R3 #0036 + 0xB80E0E00, // 0030 GETNGBL R3 K7 + 0x8C0C0708, // 0031 GETMET R3 R3 K8 + 0x58140012, // 0032 LDCONST R5 K18 + 0x5818000A, // 0033 LDCONST R6 K10 + 0x7C0C0600, // 0034 CALL R3 3 + 0x7002000B, // 0035 JMP #0042 + 0xA40E2600, // 0036 IMPORT R3 K19 + 0x60100011, // 0037 GETGBL R4 G17 + 0x5C140400, // 0038 MOVE R5 R2 + 0x58180014, // 0039 LDCONST R6 K20 + 0x7C100400, // 003A CALL R4 2 + 0x8C140915, // 003B GETMET R5 R4 K21 + 0x7C140200, // 003C CALL R5 1 + 0x8C180916, // 003D GETMET R6 R4 K22 + 0x7C180200, // 003E CALL R6 1 + 0x8C180717, // 003F GETMET R6 R3 K23 + 0x5C200A00, // 0040 MOVE R8 R5 + 0x7C180400, // 0041 CALL R6 2 + 0x880C0100, // 0042 GETMBR R3 R0 K0 + 0x000C0718, // 0043 ADD R3 R3 K24 + 0x5C080600, // 0044 MOVE R2 R3 + 0x8C0C0304, // 0045 GETMET R3 R1 K4 + 0x5C140400, // 0046 MOVE R5 R2 + 0x7C0C0400, // 0047 CALL R3 2 + 0x780E000C, // 0048 JMPF R3 #0056 + 0xB80E0E00, // 0049 GETNGBL R3 K7 + 0x8C0C0708, // 004A GETMET R3 R3 K8 + 0x00163202, // 004B ADD R5 K25 R2 + 0x5818001A, // 004C LDCONST R6 K26 + 0x7C0C0600, // 004D CALL R3 3 + 0x8C0C0106, // 004E GETMET R3 R0 K6 + 0x5C140400, // 004F MOVE R5 R2 + 0x7C0C0400, // 0050 CALL R3 2 + 0xB80E0E00, // 0051 GETNGBL R3 K7 + 0x8C0C0708, // 0052 GETMET R3 R3 K8 + 0x00163602, // 0053 ADD R5 K27 R2 + 0x5818001A, // 0054 LDCONST R6 K26 + 0x7C0C0600, // 0055 CALL R3 3 + 0x880C0100, // 0056 GETMBR R3 R0 K0 + 0x000C071C, // 0057 ADD R3 R3 K28 + 0x5C080600, // 0058 MOVE R2 R3 + 0x8C0C0304, // 0059 GETMET R3 R1 K4 + 0x5C140400, // 005A MOVE R5 R2 + 0x7C0C0400, // 005B CALL R3 2 + 0x780E000C, // 005C JMPF R3 #006A + 0xB80E0E00, // 005D GETNGBL R3 K7 + 0x8C0C0708, // 005E GETMET R3 R3 K8 + 0x00163A02, // 005F ADD R5 K29 R2 + 0x5818001A, // 0060 LDCONST R6 K26 + 0x7C0C0600, // 0061 CALL R3 3 + 0xB80E3C00, // 0062 GETNGBL R3 K30 + 0x5C100400, // 0063 MOVE R4 R2 + 0x7C0C0200, // 0064 CALL R3 1 + 0xB80E0E00, // 0065 GETNGBL R3 K7 + 0x8C0C0708, // 0066 GETMET R3 R3 K8 + 0x00163E02, // 0067 ADD R5 K31 R2 + 0x5818001A, // 0068 LDCONST R6 K26 + 0x7C0C0600, // 0069 CALL R3 3 + 0x80000000, // 006A RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: run_bat +********************************************************************/ +be_local_closure(run_bat, /* name */ + be_nested_proto( + 13, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[10]) { /* constants */ + /* K0 */ be_nested_string("string", 398550328, 6), + /* K1 */ be_nested_string("r", -150190315, 1), + /* K2 */ be_nested_string("readline", 1212709927, 8), + /* K3 */ be_const_int(0), + /* K4 */ be_nested_string("\n", 252472541, 1), + /* K5 */ be_nested_string("tasmota", 424643812, 7), + /* K6 */ be_nested_string("cmd", -158181397, 3), + /* K7 */ be_nested_string("close", 667630371, 5), + /* K8 */ be_nested_string("format", -1180859054, 6), + /* K9 */ be_nested_string("CFG: could not run %s (%s - %s)", 1428829580, 31), + }), + (be_nested_const_str("run_bat", -1758063998, 7)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[54]) { /* code */ + 0xA40A0000, // 0000 IMPORT R2 K0 + 0x4C0C0000, // 0001 LDNIL R3 + 0xA8020023, // 0002 EXBLK 0 #0027 + 0x60100011, // 0003 GETGBL R4 G17 + 0x5C140200, // 0004 MOVE R5 R1 + 0x58180001, // 0005 LDCONST R6 K1 + 0x7C100400, // 0006 CALL R4 2 + 0x5C0C0800, // 0007 MOVE R3 R4 + 0x50100200, // 0008 LDBOOL R4 1 0 + 0x78120018, // 0009 JMPF R4 #0023 + 0x8C100702, // 000A GETMET R4 R3 K2 + 0x7C100200, // 000B CALL R4 1 + 0x6014000C, // 000C GETGBL R5 G12 + 0x5C180800, // 000D MOVE R6 R4 + 0x7C140200, // 000E CALL R5 1 + 0x1C140B03, // 000F EQ R5 R5 K3 + 0x78160000, // 0010 JMPF R5 #0012 + 0x70020010, // 0011 JMP #0023 + 0x5415FFFE, // 0012 LDINT R5 -1 + 0x94140805, // 0013 GETIDX R5 R4 R5 + 0x1C140B04, // 0014 EQ R5 R5 K4 + 0x78160002, // 0015 JMPF R5 #0019 + 0x5415FFFD, // 0016 LDINT R5 -2 + 0x40160605, // 0017 CONNECT R5 K3 R5 + 0x94100805, // 0018 GETIDX R4 R4 R5 + 0x6014000C, // 0019 GETGBL R5 G12 + 0x5C180800, // 001A MOVE R6 R4 + 0x7C140200, // 001B CALL R5 1 + 0x24140B03, // 001C GT R5 R5 K3 + 0x78160003, // 001D JMPF R5 #0022 + 0xB8160A00, // 001E GETNGBL R5 K5 + 0x8C140B06, // 001F GETMET R5 R5 K6 + 0x5C1C0800, // 0020 MOVE R7 R4 + 0x7C140400, // 0021 CALL R5 2 + 0x7001FFE4, // 0022 JMP #0008 + 0x8C100707, // 0023 GETMET R4 R3 K7 + 0x7C100200, // 0024 CALL R4 1 + 0xA8040001, // 0025 EXBLK 1 1 + 0x7002000D, // 0026 JMP #0035 + 0xAC100002, // 0027 CATCH R4 0 2 + 0x7002000A, // 0028 JMP #0034 + 0x60180001, // 0029 GETGBL R6 G1 + 0x8C1C0508, // 002A GETMET R7 R2 K8 + 0x58240009, // 002B LDCONST R9 K9 + 0x5C280200, // 002C MOVE R10 R1 + 0x5C2C0800, // 002D MOVE R11 R4 + 0x5C300A00, // 002E MOVE R12 R5 + 0x7C1C0A00, // 002F CALL R7 5 + 0x7C180200, // 0030 CALL R6 1 + 0x8C180707, // 0031 GETMET R6 R3 K7 + 0x7C180200, // 0032 CALL R6 1 + 0x70020000, // 0033 JMP #0035 + 0xB0080000, // 0034 RAISE 2 R0 R0 + 0x80000000, // 0035 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: page_autoconf_mgr +********************************************************************/ +be_local_closure(page_autoconf_mgr, /* name */ + be_nested_proto( + 19, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[38]) { /* constants */ + /* K0 */ be_nested_string("webserver", 1572454038, 9), + /* K1 */ be_nested_string("string", 398550328, 6), + /* K2 */ be_nested_string("check_privileged_access", -602033328, 23), + /* K3 */ be_nested_string("content_start", -1357458227, 13), + /* K4 */ be_nested_string("Auto-configuration", 1665006109, 18), + /* K5 */ be_nested_string("content_send_style", 1087907647, 18), + /* K6 */ be_nested_string("content_send", 1673733649, 12), + /* K7 */ be_nested_string("

 (This feature requires an internet connection)

", -1575700810, 74), + /* K8 */ be_nested_string("get_current_module_path", -1088293888, 23), + /* K9 */ be_nested_string("tr", 1195724803, 2), + /* K10 */ be_nested_string("_", -636741266, 1), + /* K11 */ be_nested_string(" ", 621580159, 1), + /* K12 */ be_nested_string("_error", 1132109656, 6), + /* K13 */ be_nested_string("<Error: apply new or remove>", -1439459347, 34), + /* K14 */ be_nested_string("<None>", -1692801798, 12), + /* K15 */ be_nested_string("
", 842307168, 77), + /* K16 */ be_nested_string("format", -1180859054, 6), + /* K17 */ be_nested_string(" Current auto-configuration", -82466516, 82), + /* K18 */ be_nested_string("

Current configuration:

%s

", -179311535, 46), + /* K19 */ be_nested_string("

", 232646018, 57), + /* K21 */ be_nested_string("", -1147033080, 82), + /* K22 */ be_nested_string("

", -748395557, 11), + /* K23 */ be_nested_string("

", 2052843416, 25), + /* K24 */ be_nested_string(" Select new auto-configuration", 1926223891, 80), + /* K25 */ be_nested_string("

", -502554737, 94), + /* K27 */ be_nested_string("
", 1336654704, 49), + /* K28 */ be_nested_string("

", 1863865923, 16), + /* K34 */ be_nested_string("", 1205771629, 72), + /* K35 */ be_nested_string("content_button", 1956476087, 14), + /* K36 */ be_nested_string("BUTTON_CONFIGURATION", 70820856, 20), + /* K37 */ be_nested_string("content_stop", 658554751, 12), + }), + (be_nested_const_str("page_autoconf_mgr", -651030265, 17)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[124]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0xA40A0200, // 0001 IMPORT R2 K1 + 0x8C0C0302, // 0002 GETMET R3 R1 K2 + 0x7C0C0200, // 0003 CALL R3 1 + 0x740E0001, // 0004 JMPT R3 #0007 + 0x4C0C0000, // 0005 LDNIL R3 + 0x80040600, // 0006 RET 1 R3 + 0x8C0C0303, // 0007 GETMET R3 R1 K3 + 0x58140004, // 0008 LDCONST R5 K4 + 0x7C0C0400, // 0009 CALL R3 2 + 0x8C0C0305, // 000A GETMET R3 R1 K5 + 0x7C0C0200, // 000B CALL R3 1 + 0x8C0C0306, // 000C GETMET R3 R1 K6 + 0x58140007, // 000D LDCONST R5 K7 + 0x7C0C0400, // 000E CALL R3 2 + 0x8C0C0108, // 000F GETMET R3 R0 K8 + 0x7C0C0200, // 0010 CALL R3 1 + 0x780E0006, // 0011 JMPF R3 #0019 + 0x8C100509, // 0012 GETMET R4 R2 K9 + 0x8C180108, // 0013 GETMET R6 R0 K8 + 0x7C180200, // 0014 CALL R6 1 + 0x581C000A, // 0015 LDCONST R7 K10 + 0x5820000B, // 0016 LDCONST R8 K11 + 0x7C100800, // 0017 CALL R4 4 + 0x70020004, // 0018 JMP #001E + 0x8810010C, // 0019 GETMBR R4 R0 K12 + 0x78120001, // 001A JMPF R4 #001D + 0x5810000D, // 001B LDCONST R4 K13 + 0x70020000, // 001C JMP #001E + 0x5810000E, // 001D LDCONST R4 K14 + 0x8C140306, // 001E GETMET R5 R1 K6 + 0x581C000F, // 001F LDCONST R7 K15 + 0x7C140400, // 0020 CALL R5 2 + 0x8C140306, // 0021 GETMET R5 R1 K6 + 0x8C1C0510, // 0022 GETMET R7 R2 K16 + 0x58240011, // 0023 LDCONST R9 K17 + 0x7C1C0400, // 0024 CALL R7 2 + 0x7C140400, // 0025 CALL R5 2 + 0x8C140306, // 0026 GETMET R5 R1 K6 + 0x8C1C0510, // 0027 GETMET R7 R2 K16 + 0x58240012, // 0028 LDCONST R9 K18 + 0x5C280800, // 0029 MOVE R10 R4 + 0x7C1C0600, // 002A CALL R7 3 + 0x7C140400, // 002B CALL R5 2 + 0x780E000B, // 002C JMPF R3 #0039 + 0x8C140306, // 002D GETMET R5 R1 K6 + 0x581C0013, // 002E LDCONST R7 K19 + 0x7C140400, // 002F CALL R5 2 + 0x8C140306, // 0030 GETMET R5 R1 K6 + 0x581C0014, // 0031 LDCONST R7 K20 + 0x7C140400, // 0032 CALL R5 2 + 0x8C140306, // 0033 GETMET R5 R1 K6 + 0x581C0015, // 0034 LDCONST R7 K21 + 0x7C140400, // 0035 CALL R5 2 + 0x8C140306, // 0036 GETMET R5 R1 K6 + 0x581C0016, // 0037 LDCONST R7 K22 + 0x7C140400, // 0038 CALL R5 2 + 0x8C140306, // 0039 GETMET R5 R1 K6 + 0x581C0017, // 003A LDCONST R7 K23 + 0x7C140400, // 003B CALL R5 2 + 0x8C140306, // 003C GETMET R5 R1 K6 + 0x581C000F, // 003D LDCONST R7 K15 + 0x7C140400, // 003E CALL R5 2 + 0x8C140306, // 003F GETMET R5 R1 K6 + 0x8C1C0510, // 0040 GETMET R7 R2 K16 + 0x58240018, // 0041 LDCONST R9 K24 + 0x7C1C0400, // 0042 CALL R7 2 + 0x7C140400, // 0043 CALL R5 2 + 0x8C140306, // 0044 GETMET R5 R1 K6 + 0x581C0019, // 0045 LDCONST R7 K25 + 0x7C140400, // 0046 CALL R5 2 + 0x8C140306, // 0047 GETMET R5 R1 K6 + 0x581C001A, // 0048 LDCONST R7 K26 + 0x7C140400, // 0049 CALL R5 2 + 0x8C140306, // 004A GETMET R5 R1 K6 + 0x581C001B, // 004B LDCONST R7 K27 + 0x7C140400, // 004C CALL R5 2 + 0x8C140306, // 004D GETMET R5 R1 K6 + 0x581C001C, // 004E LDCONST R7 K28 + 0x7C140400, // 004F CALL R5 2 + 0x8C14011D, // 0050 GETMET R5 R0 K29 + 0x7C140200, // 0051 CALL R5 1 + 0x8C180306, // 0052 GETMET R6 R1 K6 + 0x5820001E, // 0053 LDCONST R8 K30 + 0x7C180400, // 0054 CALL R6 2 + 0x60180010, // 0055 GETGBL R6 G16 + 0x5C1C0A00, // 0056 MOVE R7 R5 + 0x7C180200, // 0057 CALL R6 1 + 0xA802000D, // 0058 EXBLK 0 #0067 + 0x5C1C0C00, // 0059 MOVE R7 R6 + 0x7C1C0000, // 005A CALL R7 0 + 0x8C200306, // 005B GETMET R8 R1 K6 + 0x8C280510, // 005C GETMET R10 R2 K16 + 0x5830001F, // 005D LDCONST R12 K31 + 0x5C340E00, // 005E MOVE R13 R7 + 0x8C380509, // 005F GETMET R14 R2 K9 + 0x5C400E00, // 0060 MOVE R16 R7 + 0x5844000A, // 0061 LDCONST R17 K10 + 0x5848000B, // 0062 LDCONST R18 K11 + 0x7C380800, // 0063 CALL R14 4 + 0x7C280800, // 0064 CALL R10 4 + 0x7C200400, // 0065 CALL R8 2 + 0x7001FFF1, // 0066 JMP #0059 + 0x58180020, // 0067 LDCONST R6 K32 + 0xAC180200, // 0068 CATCH R6 1 0 + 0xB0080000, // 0069 RAISE 2 R0 R0 + 0x8C180306, // 006A GETMET R6 R1 K6 + 0x58200021, // 006B LDCONST R8 K33 + 0x7C180400, // 006C CALL R6 2 + 0x8C180306, // 006D GETMET R6 R1 K6 + 0x58200022, // 006E LDCONST R8 K34 + 0x7C180400, // 006F CALL R6 2 + 0x8C180306, // 0070 GETMET R6 R1 K6 + 0x58200016, // 0071 LDCONST R8 K22 + 0x7C180400, // 0072 CALL R6 2 + 0x8C180306, // 0073 GETMET R6 R1 K6 + 0x58200017, // 0074 LDCONST R8 K23 + 0x7C180400, // 0075 CALL R6 2 + 0x8C180323, // 0076 GETMET R6 R1 K35 + 0x88200324, // 0077 GETMBR R8 R1 K36 + 0x7C180400, // 0078 CALL R6 2 + 0x8C180325, // 0079 GETMET R6 R1 K37 + 0x7C180200, // 007A CALL R6 1 + 0x80000000, // 007B RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_current_module_name +********************************************************************/ +be_local_closure(get_current_module_name, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_string("_archive", -290407892, 8), + /* K1 */ be_const_int(0), + }), + (be_nested_const_str("get_current_module_name", -1915696556, 23)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 5]) { /* code */ + 0x5405FFF2, // 0000 LDINT R1 -13 + 0x40060201, // 0001 CONNECT R1 K1 R1 + 0x88080100, // 0002 GETMBR R2 R0 K0 + 0x94040401, // 0003 GETIDX R1 R2 R1 + 0x80040200, // 0004 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: delete_all_configs +********************************************************************/ +be_local_closure(delete_all_configs, /* name */ + be_nested_proto( + 10, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 9]) { /* constants */ + /* K0 */ be_nested_string("path", -2071507658, 4), + /* K1 */ be_nested_string("string", 398550328, 6), + /* K2 */ be_nested_string("listdir", 2005220720, 7), + /* K3 */ be_nested_string("/", 705468254, 1), + /* K4 */ be_nested_string("find", -1108310694, 4), + /* K5 */ be_nested_string("_autoconf.zip", 1641927766, 13), + /* K6 */ be_const_int(0), + /* K7 */ be_nested_string("remove", -611183107, 6), + /* K8 */ be_nested_string("stop_iteration", -121173395, 14), + }), + (be_nested_const_str("delete_all_configs", -1912899718, 18)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[25]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0xA40A0200, // 0001 IMPORT R2 K1 + 0x8C0C0302, // 0002 GETMET R3 R1 K2 + 0x58140003, // 0003 LDCONST R5 K3 + 0x7C0C0400, // 0004 CALL R3 2 + 0x60100010, // 0005 GETGBL R4 G16 + 0x5C140600, // 0006 MOVE R5 R3 + 0x7C100200, // 0007 CALL R4 1 + 0xA802000B, // 0008 EXBLK 0 #0015 + 0x5C140800, // 0009 MOVE R5 R4 + 0x7C140000, // 000A CALL R5 0 + 0x8C180504, // 000B GETMET R6 R2 K4 + 0x5C200A00, // 000C MOVE R8 R5 + 0x58240005, // 000D LDCONST R9 K5 + 0x7C180600, // 000E CALL R6 3 + 0x24180D06, // 000F GT R6 R6 K6 + 0x781A0002, // 0010 JMPF R6 #0014 + 0x8C180307, // 0011 GETMET R6 R1 K7 + 0x5C200A00, // 0012 MOVE R8 R5 + 0x7C180400, // 0013 CALL R6 2 + 0x7001FFF3, // 0014 JMP #0009 + 0x58100008, // 0015 LDCONST R4 K8 + 0xAC100200, // 0016 CATCH R4 1 0 + 0xB0080000, // 0017 RAISE 2 R0 R0 + 0x80000000, // 0018 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_first_time +********************************************************************/ +be_local_closure(set_first_time, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_string("/.autoconf", -2082892903, 10), + /* K1 */ be_nested_string("w", -234078410, 1), + /* K2 */ be_nested_string("close", 667630371, 5), + }), + (be_nested_const_str("set_first_time", -1183719746, 14)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 7]) { /* code */ + 0x60040011, // 0000 GETGBL R1 G17 + 0x58080000, // 0001 LDCONST R2 K0 + 0x580C0001, // 0002 LDCONST R3 K1 + 0x7C040400, // 0003 CALL R1 2 + 0x8C080302, // 0004 GETMET R2 R1 K2 + 0x7C080200, // 0005 CALL R2 1 + 0x80000000, // 0006 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: load_templates +********************************************************************/ +be_local_closure(load_templates, /* name */ + be_nested_proto( + 15, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[21]) { /* constants */ + /* K0 */ be_nested_string("string", 398550328, 6), + /* K1 */ be_nested_string("json", 916562499, 4), + /* K2 */ be_nested_string("format", -1180859054, 6), + /* K3 */ be_nested_string("https://raw.githubusercontent.com/tasmota/autoconf/main/%s_manifest.json", -637415251, 72), + /* K4 */ be_nested_string("tasmota", 424643812, 7), + /* K5 */ be_nested_string("arch", -1342162999, 4), + /* K6 */ be_nested_string("log", 1062293841, 3), + /* K7 */ be_nested_string("CFG: loading '%s'", -2009661199, 17), + /* K8 */ be_const_int(3), + /* K9 */ be_nested_string("webclient", -218578150, 9), + /* K10 */ be_nested_string("begin", 1748273790, 5), + /* K11 */ be_nested_string("GET", -1763262857, 3), + /* K12 */ be_nested_string("CFG: return_code=%i", 2059897320, 19), + /* K13 */ be_const_int(2), + /* K14 */ be_nested_string("get_string", -99119327, 10), + /* K15 */ be_nested_string("close", 667630371, 5), + /* K16 */ be_nested_string("load", -435725847, 4), + /* K17 */ be_nested_string("CFG: loaded '%s'", 1699028828, 16), + /* K18 */ be_nested_string("find", -1108310694, 4), + /* K19 */ be_nested_string("zip", -1417514060, 3), + /* K20 */ be_nested_string("CFG: exception '%s' - '%s'", -199559383, 26), + }), + (be_nested_const_str("load_templates", -781097163, 14)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[86]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0xA40A0200, // 0001 IMPORT R2 K1 + 0xA8020042, // 0002 EXBLK 0 #0046 + 0x8C0C0302, // 0003 GETMET R3 R1 K2 + 0x58140003, // 0004 LDCONST R5 K3 + 0xB81A0800, // 0005 GETNGBL R6 K4 + 0x8C180D05, // 0006 GETMET R6 R6 K5 + 0x7C180200, // 0007 CALL R6 1 + 0x7C0C0600, // 0008 CALL R3 3 + 0xB8120800, // 0009 GETNGBL R4 K4 + 0x8C100906, // 000A GETMET R4 R4 K6 + 0x8C180302, // 000B GETMET R6 R1 K2 + 0x58200007, // 000C LDCONST R8 K7 + 0x5C240600, // 000D MOVE R9 R3 + 0x7C180600, // 000E CALL R6 3 + 0x581C0008, // 000F LDCONST R7 K8 + 0x7C100600, // 0010 CALL R4 3 + 0xB8121200, // 0011 GETNGBL R4 K9 + 0x7C100000, // 0012 CALL R4 0 + 0x8C14090A, // 0013 GETMET R5 R4 K10 + 0x5C1C0600, // 0014 MOVE R7 R3 + 0x7C140400, // 0015 CALL R5 2 + 0x8C14090B, // 0016 GETMET R5 R4 K11 + 0x7C140200, // 0017 CALL R5 1 + 0x541A00C7, // 0018 LDINT R6 200 + 0x20180A06, // 0019 NE R6 R5 R6 + 0x781A000A, // 001A JMPF R6 #0026 + 0xB81A0800, // 001B GETNGBL R6 K4 + 0x8C180D06, // 001C GETMET R6 R6 K6 + 0x8C200302, // 001D GETMET R8 R1 K2 + 0x5828000C, // 001E LDCONST R10 K12 + 0x5C2C0A00, // 001F MOVE R11 R5 + 0x7C200600, // 0020 CALL R8 3 + 0x5824000D, // 0021 LDCONST R9 K13 + 0x7C180600, // 0022 CALL R6 3 + 0x4C180000, // 0023 LDNIL R6 + 0xA8040001, // 0024 EXBLK 1 1 + 0x80040C00, // 0025 RET 1 R6 + 0x8C18090E, // 0026 GETMET R6 R4 K14 + 0x7C180200, // 0027 CALL R6 1 + 0x8C1C090F, // 0028 GETMET R7 R4 K15 + 0x7C1C0200, // 0029 CALL R7 1 + 0x8C1C0510, // 002A GETMET R7 R2 K16 + 0x5C240C00, // 002B MOVE R9 R6 + 0x7C1C0400, // 002C CALL R7 2 + 0xB8220800, // 002D GETNGBL R8 K4 + 0x8C201106, // 002E GETMET R8 R8 K6 + 0x8C280302, // 002F GETMET R10 R1 K2 + 0x58300011, // 0030 LDCONST R12 K17 + 0x60340008, // 0031 GETGBL R13 G8 + 0x5C380E00, // 0032 MOVE R14 R7 + 0x7C340200, // 0033 CALL R13 1 + 0x7C280600, // 0034 CALL R10 3 + 0x582C0008, // 0035 LDCONST R11 K8 + 0x7C200600, // 0036 CALL R8 3 + 0x8C200F12, // 0037 GETMET R8 R7 K18 + 0x58280013, // 0038 LDCONST R10 K19 + 0x7C200400, // 0039 CALL R8 2 + 0x6024000F, // 003A GETGBL R9 G15 + 0x5C281000, // 003B MOVE R10 R8 + 0x602C0012, // 003C GETGBL R11 G18 + 0x7C240400, // 003D CALL R9 2 + 0x78260001, // 003E JMPF R9 #0041 + 0xA8040001, // 003F EXBLK 1 1 + 0x80041000, // 0040 RET 1 R8 + 0x4C240000, // 0041 LDNIL R9 + 0xA8040001, // 0042 EXBLK 1 1 + 0x80041200, // 0043 RET 1 R9 + 0xA8040001, // 0044 EXBLK 1 1 + 0x7002000E, // 0045 JMP #0055 + 0xAC0C0002, // 0046 CATCH R3 0 2 + 0x7002000B, // 0047 JMP #0054 + 0xB8160800, // 0048 GETNGBL R5 K4 + 0x8C140B06, // 0049 GETMET R5 R5 K6 + 0x8C1C0302, // 004A GETMET R7 R1 K2 + 0x58240014, // 004B LDCONST R9 K20 + 0x5C280600, // 004C MOVE R10 R3 + 0x5C2C0800, // 004D MOVE R11 R4 + 0x7C1C0800, // 004E CALL R7 4 + 0x5820000D, // 004F LDCONST R8 K13 + 0x7C140600, // 0050 CALL R5 3 + 0x4C140000, // 0051 LDNIL R5 + 0x80040A00, // 0052 RET 1 R5 + 0x70020000, // 0053 JMP #0055 + 0xB0080000, // 0054 RAISE 2 R0 R0 + 0x80000000, // 0055 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: web_add_config_button +********************************************************************/ +be_local_closure(web_add_config_button, /* name */ + be_nested_proto( + 5, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_string("webserver", 1572454038, 9), + /* K1 */ be_nested_string("content_send", 1673733649, 12), + /* K2 */ be_nested_string("

", 452285201, 120), + }), + (be_nested_const_str("web_add_config_button", 639674325, 21)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 5]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0x8C080301, // 0001 GETMET R2 R1 K1 + 0x58100002, // 0002 LDCONST R4 K2 + 0x7C080400, // 0003 CALL R2 2 + 0x80000000, // 0004 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: is_first_time +********************************************************************/ +be_local_closure(is_first_time, /* name */ + be_nested_proto( + 5, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_string("path", -2071507658, 4), + /* K1 */ be_nested_string("exists", 1002329533, 6), + /* K2 */ be_nested_string("/.autoconf", -2082892903, 10), + }), + (be_nested_const_str("is_first_time", 275242384, 13)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 8]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0x8C080301, // 0001 GETMET R2 R1 K1 + 0x58100002, // 0002 LDCONST R4 K2 + 0x7C080400, // 0003 CALL R2 2 + 0x780A0000, // 0004 JMPF R2 #0006 + 0x50080001, // 0005 LDBOOL R2 0 1 + 0x50080200, // 0006 LDBOOL R2 1 0 + 0x80040400, // 0007 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(init, /* name */ + be_nested_proto( + 12, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[15]) { /* constants */ + /* K0 */ be_nested_string("path", -2071507658, 4), + /* K1 */ be_nested_string("string", 398550328, 6), + /* K2 */ be_nested_string("listdir", 2005220720, 7), + /* K3 */ be_nested_string("/", 705468254, 1), + /* K4 */ be_nested_string("tasmota", 424643812, 7), + /* K5 */ be_nested_string("add_driver", 1654458371, 10), + /* K6 */ be_const_int(0), + /* K7 */ be_nested_string("find", -1108310694, 4), + /* K8 */ be_nested_string("_autoconf.zip", 1641927766, 13), + /* K9 */ be_nested_string("format", -1180859054, 6), + /* K10 */ be_nested_string("CFG: multiple autoconf files found, aborting ('%s' + '%s')", 197663371, 58), + /* K11 */ be_nested_string("_error", 1132109656, 6), + /* K12 */ be_const_int(1), + /* K13 */ be_nested_string("CFG: no '*_autoconf.zip' file found", -1047382425, 35), + /* K14 */ be_nested_string("_archive", -290407892, 8), + }), + (be_nested_const_str("init", 380752755, 4)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[49]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0xA40A0200, // 0001 IMPORT R2 K1 + 0x8C0C0302, // 0002 GETMET R3 R1 K2 + 0x58140003, // 0003 LDCONST R5 K3 + 0x7C0C0400, // 0004 CALL R3 2 + 0x4C100000, // 0005 LDNIL R4 + 0xB8160800, // 0006 GETNGBL R5 K4 + 0x8C140B05, // 0007 GETMET R5 R5 K5 + 0x5C1C0000, // 0008 MOVE R7 R0 + 0x7C140400, // 0009 CALL R5 2 + 0x58140006, // 000A LDCONST R5 K6 + 0x6018000C, // 000B GETGBL R6 G12 + 0x5C1C0600, // 000C MOVE R7 R3 + 0x7C180200, // 000D CALL R6 1 + 0x14180A06, // 000E LT R6 R5 R6 + 0x781A0016, // 000F JMPF R6 #0027 + 0x8C180507, // 0010 GETMET R6 R2 K7 + 0x94200605, // 0011 GETIDX R8 R3 R5 + 0x58240008, // 0012 LDCONST R9 K8 + 0x7C180600, // 0013 CALL R6 3 + 0x24180D06, // 0014 GT R6 R6 K6 + 0x781A000E, // 0015 JMPF R6 #0025 + 0x4C180000, // 0016 LDNIL R6 + 0x20180806, // 0017 NE R6 R4 R6 + 0x781A000A, // 0018 JMPF R6 #0024 + 0x60180001, // 0019 GETGBL R6 G1 + 0x8C1C0509, // 001A GETMET R7 R2 K9 + 0x5824000A, // 001B LDCONST R9 K10 + 0x5C280800, // 001C MOVE R10 R4 + 0x942C0605, // 001D GETIDX R11 R3 R5 + 0x7C1C0800, // 001E CALL R7 4 + 0x7C180200, // 001F CALL R6 1 + 0x50180200, // 0020 LDBOOL R6 1 0 + 0x90021606, // 0021 SETMBR R0 K11 R6 + 0x4C180000, // 0022 LDNIL R6 + 0x80040C00, // 0023 RET 1 R6 + 0x94100605, // 0024 GETIDX R4 R3 R5 + 0x00140B0C, // 0025 ADD R5 R5 K12 + 0x7001FFE3, // 0026 JMP #000B + 0x4C180000, // 0027 LDNIL R6 + 0x1C180806, // 0028 EQ R6 R4 R6 + 0x781A0004, // 0029 JMPF R6 #002F + 0x60180001, // 002A GETGBL R6 G1 + 0x581C000D, // 002B LDCONST R7 K13 + 0x7C180200, // 002C CALL R6 1 + 0x4C180000, // 002D LDNIL R6 + 0x80040C00, // 002E RET 1 R6 + 0x90021C04, // 002F SETMBR R0 K14 R4 + 0x80000000, // 0030 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: preinit +********************************************************************/ +be_local_closure(preinit, /* name */ + be_nested_proto( + 7, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[10]) { /* constants */ + /* K0 */ be_nested_string("_archive", -290407892, 8), + /* K1 */ be_nested_string("path", -2071507658, 4), + /* K2 */ be_nested_string("#preinit.be", 687035716, 11), + /* K3 */ be_nested_string("exists", 1002329533, 6), + /* K4 */ be_nested_string("tasmota", 424643812, 7), + /* K5 */ be_nested_string("log", 1062293841, 3), + /* K6 */ be_nested_string("CFG: loading ", -284605793, 13), + /* K7 */ be_const_int(3), + /* K8 */ be_nested_string("load", -435725847, 4), + /* K9 */ be_nested_string("CFG: loaded ", -584693758, 13), + }), + (be_nested_const_str("preinit", -1572960196, 7)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[26]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x4C080000, // 0001 LDNIL R2 + 0x1C040202, // 0002 EQ R1 R1 R2 + 0x78060000, // 0003 JMPF R1 #0005 + 0x80000200, // 0004 RET 0 + 0xA4060200, // 0005 IMPORT R1 K1 + 0x88080100, // 0006 GETMBR R2 R0 K0 + 0x00080502, // 0007 ADD R2 R2 K2 + 0x8C0C0303, // 0008 GETMET R3 R1 K3 + 0x5C140400, // 0009 MOVE R5 R2 + 0x7C0C0400, // 000A CALL R3 2 + 0x780E000C, // 000B JMPF R3 #0019 + 0xB80E0800, // 000C GETNGBL R3 K4 + 0x8C0C0705, // 000D GETMET R3 R3 K5 + 0x00160C02, // 000E ADD R5 K6 R2 + 0x58180007, // 000F LDCONST R6 K7 + 0x7C0C0600, // 0010 CALL R3 3 + 0xB80E1000, // 0011 GETNGBL R3 K8 + 0x5C100400, // 0012 MOVE R4 R2 + 0x7C0C0200, // 0013 CALL R3 1 + 0xB80E0800, // 0014 GETNGBL R3 K4 + 0x8C0C0705, // 0015 GETMET R3 R3 K5 + 0x00161202, // 0016 ADD R5 K9 R2 + 0x58180007, // 0017 LDCONST R6 K7 + 0x7C0C0600, // 0018 CALL R3 3 + 0x80000000, // 0019 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: reset +********************************************************************/ +be_local_closure(reset, /* name */ + be_nested_proto( + 12, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[13]) { /* constants */ + /* K0 */ be_nested_string("path", -2071507658, 4), + /* K1 */ be_nested_string("string", 398550328, 6), + /* K2 */ be_nested_string("listdir", 2005220720, 7), + /* K3 */ be_nested_string("/", 705468254, 1), + /* K4 */ be_const_int(0), + /* K5 */ be_nested_string("find", -1108310694, 4), + /* K6 */ be_nested_string("_autoconf.zip", 1641927766, 13), + /* K7 */ be_nested_string("remove", -611183107, 6), + /* K8 */ be_nested_string("format", -1180859054, 6), + /* K9 */ be_nested_string("CFG: removed file '%s'", 2048602473, 22), + /* K10 */ be_const_int(1), + /* K11 */ be_nested_string("_archive", -290407892, 8), + /* K12 */ be_nested_string("_error", 1132109656, 6), + }), + (be_nested_const_str("reset", 1695364032, 5)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[35]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0xA40A0200, // 0001 IMPORT R2 K1 + 0x8C0C0302, // 0002 GETMET R3 R1 K2 + 0x58140003, // 0003 LDCONST R5 K3 + 0x7C0C0400, // 0004 CALL R3 2 + 0x4C100000, // 0005 LDNIL R4 + 0x58140004, // 0006 LDCONST R5 K4 + 0x6018000C, // 0007 GETGBL R6 G12 + 0x5C1C0600, // 0008 MOVE R7 R3 + 0x7C180200, // 0009 CALL R6 1 + 0x14180A06, // 000A LT R6 R5 R6 + 0x781A0011, // 000B JMPF R6 #001E + 0x94180605, // 000C GETIDX R6 R3 R5 + 0x8C1C0505, // 000D GETMET R7 R2 K5 + 0x5C240C00, // 000E MOVE R9 R6 + 0x58280006, // 000F LDCONST R10 K6 + 0x7C1C0600, // 0010 CALL R7 3 + 0x241C0F04, // 0011 GT R7 R7 K4 + 0x781E0008, // 0012 JMPF R7 #001C + 0x8C1C0307, // 0013 GETMET R7 R1 K7 + 0x5C240C00, // 0014 MOVE R9 R6 + 0x7C1C0400, // 0015 CALL R7 2 + 0x601C0001, // 0016 GETGBL R7 G1 + 0x8C200508, // 0017 GETMET R8 R2 K8 + 0x58280009, // 0018 LDCONST R10 K9 + 0x5C2C0C00, // 0019 MOVE R11 R6 + 0x7C200600, // 001A CALL R8 3 + 0x7C1C0200, // 001B CALL R7 1 + 0x00140B0A, // 001C ADD R5 R5 K10 + 0x7001FFE8, // 001D JMP #0007 + 0x4C180000, // 001E LDNIL R6 + 0x90021606, // 001F SETMBR R0 K11 R6 + 0x4C180000, // 0020 LDNIL R6 + 0x90021806, // 0021 SETMBR R0 K12 R6 + 0x80000000, // 0022 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: web_add_handler +********************************************************************/ +be_local_closure(web_add_handler, /* name */ + be_nested_proto( + 7, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 1, /* has sup protos */ + ( &(const struct bproto*[ 2]) { + be_nested_proto( + 2, /* nstack */ + 0, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 1]) { /* upvals */ + be_local_const_upval(1, 0), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_string("page_autoconf_mgr", -651030265, 17), + }), + (be_nested_const_str("", 607256038, 8)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 4]) { /* code */ + 0x68000000, // 0000 GETUPV R0 U0 + 0x8C000100, // 0001 GETMET R0 R0 K0 + 0x7C000200, // 0002 CALL R0 1 + 0x80040000, // 0003 RET 1 R0 + }) + ), + be_nested_proto( + 2, /* nstack */ + 0, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 1]) { /* upvals */ + be_local_const_upval(1, 0), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_string("page_autoconf_ctl", -1841585800, 17), + }), + (be_nested_const_str("", 607256038, 8)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 4]) { /* code */ + 0x68000000, // 0000 GETUPV R0 U0 + 0x8C000100, // 0001 GETMET R0 R0 K0 + 0x7C000200, // 0002 CALL R0 1 + 0x80040000, // 0003 RET 1 R0 + }) + ), + }), + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_string("webserver", 1572454038, 9), + /* K1 */ be_nested_string("on", 1630810064, 2), + /* K2 */ be_nested_string("/ac", -390315318, 3), + /* K3 */ be_nested_string("HTTP_GET", 1722467738, 8), + /* K4 */ be_nested_string("HTTP_POST", 1999554144, 9), + }), + (be_nested_const_str("web_add_handler", -304792334, 15)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[13]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0x8C080301, // 0001 GETMET R2 R1 K1 + 0x58100002, // 0002 LDCONST R4 K2 + 0x84140000, // 0003 CLOSURE R5 P0 + 0x88180303, // 0004 GETMBR R6 R1 K3 + 0x7C080800, // 0005 CALL R2 4 + 0x8C080301, // 0006 GETMET R2 R1 K1 + 0x58100002, // 0007 LDCONST R4 K2 + 0x84140001, // 0008 CLOSURE R5 P1 + 0x88180304, // 0009 GETMBR R6 R1 K4 + 0x7C080800, // 000A CALL R2 4 + 0xA0000000, // 000B CLOSE R0 + 0x80000000, // 000C RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: clear_first_time +********************************************************************/ +be_local_closure(clear_first_time, /* name */ + be_nested_proto( + 5, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_string("path", -2071507658, 4), + /* K1 */ be_nested_string("remove", -611183107, 6), + /* K2 */ be_nested_string("/.autoconf", -2082892903, 10), + }), + (be_nested_const_str("clear_first_time", 632769909, 16)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 5]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0x8C080301, // 0001 GETMET R2 R1 K1 + 0x58100002, // 0002 LDCONST R4 K2 + 0x7C080400, // 0003 CALL R2 2 + 0x80000000, // 0004 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_current_module_path +********************************************************************/ +be_local_closure(get_current_module_path, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_string("_archive", -290407892, 8), + }), + (be_nested_const_str("get_current_module_path", -1088293888, 23)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Autoconf +********************************************************************/ +be_local_class(Autoconf, + 2, + NULL, + be_nested_map(18, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_nested_key("page_autoconf_ctl", -1841585800, 17, -1), be_const_closure(page_autoconf_ctl_closure) }, + { be_nested_key("autoexec", -618105405, 8, -1), be_const_closure(autoexec_closure) }, + { be_nested_key("run_bat", -1758063998, 7, 6), be_const_closure(run_bat_closure) }, + { be_nested_key("page_autoconf_mgr", -651030265, 17, -1), be_const_closure(page_autoconf_mgr_closure) }, + { be_nested_key("get_current_module_name", -1915696556, 23, -1), be_const_closure(get_current_module_name_closure) }, + { be_nested_key("delete_all_configs", -1912899718, 18, 13), be_const_closure(delete_all_configs_closure) }, + { be_nested_key("set_first_time", -1183719746, 14, -1), be_const_closure(set_first_time_closure) }, + { be_nested_key("load_templates", -781097163, 14, -1), be_const_closure(load_templates_closure) }, + { be_nested_key("_archive", -290407892, 8, -1), be_const_var(0) }, + { be_nested_key("web_add_config_button", 639674325, 21, -1), be_const_closure(web_add_config_button_closure) }, + { be_nested_key("is_first_time", 275242384, 13, -1), be_const_closure(is_first_time_closure) }, + { be_nested_key("init", 380752755, 4, -1), be_const_closure(init_closure) }, + { be_nested_key("preinit", -1572960196, 7, 5), be_const_closure(preinit_closure) }, + { be_nested_key("reset", 1695364032, 5, 17), be_const_closure(reset_closure) }, + { be_nested_key("web_add_handler", -304792334, 15, 4), be_const_closure(web_add_handler_closure) }, + { be_nested_key("clear_first_time", 632769909, 16, 11), be_const_closure(clear_first_time_closure) }, + { be_nested_key("_error", 1132109656, 6, -1), be_const_var(1) }, + { be_nested_key("get_current_module_path", -1088293888, 23, -1), be_const_closure(get_current_module_path_closure) }, + })), + (be_nested_const_str("Autoconf", 984011268, 8)) +); + +/******************************************************************** +** Solidified function: _anonymous_ +********************************************************************/ +be_local_closure(_anonymous_, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_const_class(be_class_Autoconf), + }), + (be_nested_const_str("_anonymous_", 1957281476, 11)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 5]) { /* code */ + 0x58040000, // 0000 LDCONST R1 K0 + 0xB4000000, // 0001 CLASS K0 + 0x5C080200, // 0002 MOVE R2 R1 + 0x7C080000, // 0003 CALL R2 0 + 0x80040400, // 0004 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified module: autoconf +********************************************************************/ +be_local_module(autoconf, + "autoconf", + be_nested_map(1, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_nested_key("init", 380752755, 4, -1), be_const_closure(_anonymous__closure) }, + })) +); +BE_EXPORT_VARIABLE be_define_const_native_module(autoconf); +/********************************************************************/ diff --git a/lib/libesp32/Berry/default/be_display_lib.c b/lib/libesp32/Berry/default/be_display_lib.c new file mode 100644 index 000000000..2d8bf9ff7 --- /dev/null +++ b/lib/libesp32/Berry/default/be_display_lib.c @@ -0,0 +1,29 @@ +/******************************************************************** + * Tasmota lib + * + * To use: `import display` + * + * Initialize Universal Display driver + *******************************************************************/ +#include "be_constobj.h" + +#ifdef USE_DISPLAY + +// Tasmota specific + +extern int be_disp_start(bvm *vm); + +/******************************************************************** +** Solidified module: display +********************************************************************/ +be_local_module(display, + "display", + be_nested_map(1, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_nested_key("start", 1697318111, 5, -1), be_const_func(be_disp_start) }, + })) +); +BE_EXPORT_VARIABLE be_define_const_native_module(display); +/********************************************************************/ + +#endif // USE_DISPLAY \ No newline at end of file diff --git a/lib/libesp32/Berry/default/be_modtab.c b/lib/libesp32/Berry/default/be_modtab.c index 46b5528a9..1b219658f 100644 --- a/lib/libesp32/Berry/default/be_modtab.c +++ b/lib/libesp32/Berry/default/be_modtab.c @@ -26,8 +26,10 @@ be_extern_native_module(strict); /* Tasmota specific */ be_extern_native_module(python_compat); be_extern_native_module(persist); +be_extern_native_module(autoconf); be_extern_native_module(light); be_extern_native_module(gpio); +be_extern_native_module(display); be_extern_native_module(energy); be_extern_native_module(webserver); be_extern_native_module(flash); @@ -85,7 +87,13 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = { &be_native_module(python_compat), &be_native_module(path), &be_native_module(persist), +#ifdef USE_AUTOCONF + &be_native_module(autoconf), +#endif // USE_AUTOCONF &be_native_module(gpio), +#ifdef USE_DISPLAY + &be_native_module(display), +#endif // USE_DISPLAY #ifdef USE_LIGHT &be_native_module(light), #endif diff --git a/lib/libesp32/Berry/default/be_tasmotalib.c b/lib/libesp32/Berry/default/be_tasmotalib.c index dd5c986d8..dc07a8562 100644 --- a/lib/libesp32/Berry/default/be_tasmotalib.c +++ b/lib/libesp32/Berry/default/be_tasmotalib.c @@ -141,7 +141,7 @@ be_local_closure(init, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[11]) { /* constants */ + ( &(const bvalue[13]) { /* constants */ /* K0 */ be_nested_string("global", 503252654, 6), /* K1 */ be_nested_string("ctypes_bytes_dyn", 915205307, 16), /* K2 */ be_nested_string("_global_addr", 533766721, 12), @@ -153,10 +153,12 @@ be_local_closure(init, /* name */ /* K8 */ be_nested_string("settings", 1745255176, 8), /* K9 */ be_nested_string("toptr", -915119842, 5), /* K10 */ be_nested_string("_settings_def", -519406989, 13), + /* K11 */ be_nested_string("wd", 1531424278, 2), + /* K12 */ be_nested_string("", -2128831035, 0), }), - ((bstring*) &be_const_str_init), - (be_nested_const_str("tasmota.be", 1128870755, 10)), - ( &(const binstruction[23]) { /* code */ + (be_nested_const_str("init", 380752755, 4)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[24]) { /* code */ 0xB8060200, // 0000 GETNGBL R1 K1 0x88080102, // 0001 GETMBR R2 R0 K2 0x880C0103, // 0002 GETMBR R3 R0 K3 @@ -179,7 +181,8 @@ be_local_closure(init, /* name */ 0x8814010A, // 0013 GETMBR R5 R0 K10 0x7C0C0400, // 0014 CALL R3 2 0x90021003, // 0015 SETMBR R0 K8 R3 - 0x80000000, // 0016 RET 0 + 0x9002170C, // 0016 SETMBR R0 K11 K12 + 0x80000000, // 0017 RET 0 }) ) ); @@ -850,7 +853,7 @@ be_local_closure(time_str, /* name */ ********************************************************************/ be_local_closure(load, /* name */ be_nested_proto( - 15, /* nstack */ + 19, /* nstack */ 2, /* argc */ 0, /* varg */ 0, /* has upvals */ @@ -858,116 +861,140 @@ be_local_closure(load, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[18]) { /* constants */ + ( &(const bvalue[21]) { /* constants */ /* K0 */ be_nested_string("string", 398550328, 6), /* K1 */ be_nested_string("path", -2071507658, 4), - /* K2 */ be_nested_string("find", -1108310694, 4), - /* K3 */ be_nested_string(".", 722245873, 1), - /* K4 */ be_const_int(0), - /* K5 */ be_nested_string(".be", 1325797348, 3), - /* K6 */ be_nested_string("split", -2017972765, 5), - /* K7 */ be_const_int(1), - /* K8 */ be_nested_string("be", 942383232, 2), - /* K9 */ be_nested_string("bec", 1336821081, 3), - /* K10 */ be_nested_string("io_error", 1970281036, 8), - /* K11 */ be_nested_string("file extension is not '.be' or '.bec'", -1199247657, 37), - /* K12 */ be_nested_string("c", -435409838, 1), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_string("/", 705468254, 1), + /* K4 */ be_nested_string("split", -2017972765, 5), + /* K5 */ be_nested_string("#", 638357778, 1), + /* K6 */ be_const_int(1), + /* K7 */ be_nested_string("find", -1108310694, 4), + /* K8 */ be_nested_string(".", 722245873, 1), + /* K9 */ be_nested_string(".be", 1325797348, 3), + /* K10 */ be_nested_string(".bec", -309694075, 4), + /* K11 */ be_nested_string("io_error", 1970281036, 8), + /* K12 */ be_nested_string("file extension is not '.be' or '.bec'", -1199247657, 37), /* K13 */ be_nested_string("last_modified", 772177145, 13), - /* K14 */ be_nested_string("file", -1427482813, 4), - /* K15 */ be_nested_string("save", -855671224, 4), - /* K16 */ be_nested_string("format", -1180859054, 6), - /* K17 */ be_nested_string("BRY: could not save compiled file %s (%s)", 736659787, 41), + /* K14 */ be_nested_string("c", -435409838, 1), + /* K15 */ be_nested_string("wd", 1531424278, 2), + /* K16 */ be_nested_string("", -2128831035, 0), + /* K17 */ be_nested_string("file", -1427482813, 4), + /* K18 */ be_nested_string("save", -855671224, 4), + /* K19 */ be_nested_string("format", -1180859054, 6), + /* K20 */ be_nested_string("BRY: could not save compiled file %s (%s)", 736659787, 41), }), (be_nested_const_str("load", -435725847, 4)), ((bstring*) &be_const_str_input), - ( &(const binstruction[87]) { /* code */ + ( &(const binstruction[108]) { /* code */ 0xA40A0000, // 0000 IMPORT R2 K0 0xA40E0200, // 0001 IMPORT R3 K1 - 0x8C100502, // 0002 GETMET R4 R2 K2 - 0x5C180200, // 0003 MOVE R6 R1 - 0x581C0003, // 0004 LDCONST R7 K3 - 0x7C100600, // 0005 CALL R4 3 - 0x14100904, // 0006 LT R4 R4 K4 - 0x78120000, // 0007 JMPF R4 #0009 - 0x00040305, // 0008 ADD R1 R1 K5 - 0x8C100506, // 0009 GETMET R4 R2 K6 - 0x5C180200, // 000A MOVE R6 R1 - 0x581C0003, // 000B LDCONST R7 K3 - 0x7C100600, // 000C CALL R4 3 - 0x6014000C, // 000D GETGBL R5 G12 - 0x5C180800, // 000E MOVE R6 R4 - 0x7C140200, // 000F CALL R5 1 - 0x18140B07, // 0010 LE R5 R5 K7 - 0x74160007, // 0011 JMPT R5 #001A - 0x5415FFFE, // 0012 LDINT R5 -1 - 0x94140805, // 0013 GETIDX R5 R4 R5 - 0x20140B08, // 0014 NE R5 R5 K8 - 0x78160004, // 0015 JMPF R5 #001B - 0x5415FFFE, // 0016 LDINT R5 -1 - 0x94140805, // 0017 GETIDX R5 R4 R5 - 0x20140B09, // 0018 NE R5 R5 K9 - 0x78160000, // 0019 JMPF R5 #001B - 0xB006150B, // 001A RAISE 1 K10 K11 - 0x5415FFFE, // 001B LDINT R5 -1 - 0x94140205, // 001C GETIDX R5 R1 R5 - 0x1C140B0C, // 001D EQ R5 R5 K12 - 0x8C18070D, // 001E GETMET R6 R3 K13 - 0x5C200200, // 001F MOVE R8 R1 - 0x7C180400, // 0020 CALL R6 2 - 0x78160005, // 0021 JMPF R5 #0028 - 0x4C1C0000, // 0022 LDNIL R7 - 0x1C1C0C07, // 0023 EQ R7 R6 R7 - 0x781E0001, // 0024 JMPF R7 #0027 - 0x501C0000, // 0025 LDBOOL R7 0 0 - 0x80040E00, // 0026 RET 1 R7 - 0x70020013, // 0027 JMP #003C - 0x8C1C070D, // 0028 GETMET R7 R3 K13 - 0x0024030C, // 0029 ADD R9 R1 K12 - 0x7C1C0400, // 002A CALL R7 2 - 0x4C200000, // 002B LDNIL R8 - 0x1C200C08, // 002C EQ R8 R6 R8 - 0x78220004, // 002D JMPF R8 #0033 - 0x4C200000, // 002E LDNIL R8 - 0x1C200E08, // 002F EQ R8 R7 R8 - 0x78220001, // 0030 JMPF R8 #0033 - 0x50200000, // 0031 LDBOOL R8 0 0 - 0x80041000, // 0032 RET 1 R8 - 0x4C200000, // 0033 LDNIL R8 - 0x20200E08, // 0034 NE R8 R7 R8 - 0x78220005, // 0035 JMPF R8 #003C - 0x4C200000, // 0036 LDNIL R8 - 0x1C200C08, // 0037 EQ R8 R6 R8 - 0x74220001, // 0038 JMPT R8 #003B - 0x28200E06, // 0039 GE R8 R7 R6 - 0x78220000, // 003A JMPF R8 #003C - 0x50140200, // 003B LDBOOL R5 1 0 - 0x601C000D, // 003C GETGBL R7 G13 - 0x5C200200, // 003D MOVE R8 R1 - 0x5824000E, // 003E LDCONST R9 K14 - 0x7C1C0400, // 003F CALL R7 2 - 0x74160011, // 0040 JMPT R5 #0053 - 0xA8020005, // 0041 EXBLK 0 #0048 - 0x8C20010F, // 0042 GETMET R8 R0 K15 - 0x0028030C, // 0043 ADD R10 R1 K12 - 0x5C2C0E00, // 0044 MOVE R11 R7 - 0x7C200600, // 0045 CALL R8 3 - 0xA8040001, // 0046 EXBLK 1 1 - 0x7002000A, // 0047 JMP #0053 - 0xAC200001, // 0048 CATCH R8 0 1 - 0x70020007, // 0049 JMP #0052 - 0x60240001, // 004A GETGBL R9 G1 - 0x8C280510, // 004B GETMET R10 R2 K16 - 0x58300011, // 004C LDCONST R12 K17 - 0x0034030C, // 004D ADD R13 R1 K12 - 0x5C381000, // 004E MOVE R14 R8 - 0x7C280800, // 004F CALL R10 4 - 0x7C240200, // 0050 CALL R9 1 - 0x70020000, // 0051 JMP #0053 - 0xB0080000, // 0052 RAISE 2 R0 R0 - 0x5C200E00, // 0053 MOVE R8 R7 - 0x7C200000, // 0054 CALL R8 0 - 0x50200200, // 0055 LDBOOL R8 1 0 - 0x80041000, // 0056 RET 1 R8 + 0x6010000C, // 0002 GETGBL R4 G12 + 0x5C140200, // 0003 MOVE R5 R1 + 0x7C100200, // 0004 CALL R4 1 + 0x1C100902, // 0005 EQ R4 R4 K2 + 0x78120001, // 0006 JMPF R4 #0009 + 0x50100000, // 0007 LDBOOL R4 0 0 + 0x80040800, // 0008 RET 1 R4 + 0x94100302, // 0009 GETIDX R4 R1 K2 + 0x20100903, // 000A NE R4 R4 K3 + 0x78120000, // 000B JMPF R4 #000D + 0x00060601, // 000C ADD R1 K3 R1 + 0x8C100504, // 000D GETMET R4 R2 K4 + 0x5C180200, // 000E MOVE R6 R1 + 0x581C0005, // 000F LDCONST R7 K5 + 0x7C100600, // 0010 CALL R4 3 + 0x94140902, // 0011 GETIDX R5 R4 K2 + 0x5419FFFE, // 0012 LDINT R6 -1 + 0x94180806, // 0013 GETIDX R6 R4 R6 + 0x601C000C, // 0014 GETGBL R7 G12 + 0x5C200800, // 0015 MOVE R8 R4 + 0x7C1C0200, // 0016 CALL R7 1 + 0x241C0F06, // 0017 GT R7 R7 K6 + 0x8C200507, // 0018 GETMET R8 R2 K7 + 0x5C280C00, // 0019 MOVE R10 R6 + 0x582C0008, // 001A LDCONST R11 K8 + 0x7C200600, // 001B CALL R8 3 + 0x14201102, // 001C LT R8 R8 K2 + 0x78220001, // 001D JMPF R8 #0020 + 0x00040309, // 001E ADD R1 R1 K9 + 0x00180D09, // 001F ADD R6 R6 K9 + 0x5421FFFC, // 0020 LDINT R8 -3 + 0x5425FFFE, // 0021 LDINT R9 -1 + 0x40201009, // 0022 CONNECT R8 R8 R9 + 0x94200C08, // 0023 GETIDX R8 R6 R8 + 0x1C201109, // 0024 EQ R8 R8 K9 + 0x5425FFFB, // 0025 LDINT R9 -4 + 0x5429FFFE, // 0026 LDINT R10 -1 + 0x4024120A, // 0027 CONNECT R9 R9 R10 + 0x94240C09, // 0028 GETIDX R9 R6 R9 + 0x1C24130A, // 0029 EQ R9 R9 K10 + 0x74220001, // 002A JMPT R8 #002D + 0x74260000, // 002B JMPT R9 #002D + 0xB006170C, // 002C RAISE 1 K11 K12 + 0x8C28070D, // 002D GETMET R10 R3 K13 + 0x5C300A00, // 002E MOVE R12 R5 + 0x7C280400, // 002F CALL R10 2 + 0x78260005, // 0030 JMPF R9 #0037 + 0x4C2C0000, // 0031 LDNIL R11 + 0x1C2C140B, // 0032 EQ R11 R10 R11 + 0x782E0001, // 0033 JMPF R11 #0036 + 0x502C0000, // 0034 LDBOOL R11 0 0 + 0x80041600, // 0035 RET 1 R11 + 0x70020013, // 0036 JMP #004B + 0x8C2C070D, // 0037 GETMET R11 R3 K13 + 0x0034030E, // 0038 ADD R13 R1 K14 + 0x7C2C0400, // 0039 CALL R11 2 + 0x4C300000, // 003A LDNIL R12 + 0x1C30140C, // 003B EQ R12 R10 R12 + 0x78320004, // 003C JMPF R12 #0042 + 0x4C300000, // 003D LDNIL R12 + 0x1C30160C, // 003E EQ R12 R11 R12 + 0x78320001, // 003F JMPF R12 #0042 + 0x50300000, // 0040 LDBOOL R12 0 0 + 0x80041800, // 0041 RET 1 R12 + 0x4C300000, // 0042 LDNIL R12 + 0x2030160C, // 0043 NE R12 R11 R12 + 0x78320005, // 0044 JMPF R12 #004B + 0x4C300000, // 0045 LDNIL R12 + 0x1C30140C, // 0046 EQ R12 R10 R12 + 0x74320001, // 0047 JMPT R12 #004A + 0x2830160A, // 0048 GE R12 R11 R10 + 0x78320000, // 0049 JMPF R12 #004B + 0x50240200, // 004A LDBOOL R9 1 0 + 0x781E0002, // 004B JMPF R7 #004F + 0x002C0B05, // 004C ADD R11 R5 K5 + 0x90021E0B, // 004D SETMBR R0 K15 R11 + 0x70020000, // 004E JMP #0050 + 0x90021F10, // 004F SETMBR R0 K15 K16 + 0x602C000D, // 0050 GETGBL R11 G13 + 0x5C300200, // 0051 MOVE R12 R1 + 0x58340011, // 0052 LDCONST R13 K17 + 0x7C2C0400, // 0053 CALL R11 2 + 0x74260012, // 0054 JMPT R9 #0068 + 0x741E0011, // 0055 JMPT R7 #0068 + 0xA8020005, // 0056 EXBLK 0 #005D + 0x8C300112, // 0057 GETMET R12 R0 K18 + 0x0038030E, // 0058 ADD R14 R1 K14 + 0x5C3C1600, // 0059 MOVE R15 R11 + 0x7C300600, // 005A CALL R12 3 + 0xA8040001, // 005B EXBLK 1 1 + 0x7002000A, // 005C JMP #0068 + 0xAC300001, // 005D CATCH R12 0 1 + 0x70020007, // 005E JMP #0067 + 0x60340001, // 005F GETGBL R13 G1 + 0x8C380513, // 0060 GETMET R14 R2 K19 + 0x58400014, // 0061 LDCONST R16 K20 + 0x0044030E, // 0062 ADD R17 R1 K14 + 0x5C481800, // 0063 MOVE R18 R12 + 0x7C380800, // 0064 CALL R14 4 + 0x7C340200, // 0065 CALL R13 1 + 0x70020000, // 0066 JMP #0068 + 0xB0080000, // 0067 RAISE 2 R0 R0 + 0x5C301600, // 0068 MOVE R12 R11 + 0x7C300000, // 0069 CALL R12 0 + 0x50300200, // 006A LDBOOL R12 1 0 + 0x80041800, // 006B RET 1 R12 }) ) ); @@ -1856,6 +1883,7 @@ class be_class_tasmota (scope: global, name: Tasmota) { global, var settings, var cmd_res, var + wd, var _global_def, comptr(&be_tasmota_global_struct) _settings_def, comptr(&be_tasmota_settings_struct) diff --git a/lib/libesp32/Berry/default/embedded/Tasmota.be b/lib/libesp32/Berry/default/embedded/Tasmota.be index 5bccfa66c..e1d7ef10e 100644 --- a/lib/libesp32/Berry/default/embedded/Tasmota.be +++ b/lib/libesp32/Berry/default/embedded/Tasmota.be @@ -27,6 +27,7 @@ class Tasmota var cmd_res # store the command result, nil if disables, true if capture enabled, contains return value var global # mapping to TasmotaGlobal var settings + var wd # last working directory def init() # instanciate the mapping object to TasmotaGlobal @@ -36,6 +37,7 @@ class Tasmota if settings_addr self.settings = ctypes_bytes_dyn(introspect.toptr(settings_addr), self._settings_def) end + self.wd = "" end # create a specific sub-class for rules: pattern(string) -> closure @@ -324,21 +326,39 @@ class Tasmota import string import path - # if the filename has no '.' append '.be' - if string.find(f, '.') < 0 + # fail if empty string + if size(f) == 0 return false end + # Ex: f = 'app.zip#autoexec' + + # add leading '/' if absent + if f[0] != '/' f = '/' + f end + # Ex: f = '/app.zip#autoexec' + + var f_items = string.split(f, '#') + var f_prefix = f_items[0] + var f_suffix = f_items[-1] # last token + var f_archive = size(f_items) > 1 # is the file in an archive + + # if no dot, add the default '.be' extension + if string.find(f_suffix, '.') < 0 # does the final file has a '.' f += ".be" + f_suffix += ".be" end + # Ex: f = '/app.zip#autoexec.be' + + # if the filename has no '.' append '.be' + var suffix_be = f_suffix[-3..-1] == '.be' + var suffix_bec = f_suffix[-4..-1] == '.bec' + # Ex: f = '/app.zip#autoexec.be', f_suffix = 'autoexec.be', suffix_be = true, suffix_bec = false # check that the file ends with '.be' of '.bec' - var fl = string.split(f,'.') - if (size(fl) <= 1 || (fl[-1] != 'be' && fl[-1] != 'bec')) + if !suffix_be && !suffix_bec raise "io_error", "file extension is not '.be' or '.bec'" end - var is_bytecode = f[-1] == 'c' # file is Berry source and not bytecode - var f_time = path.last_modified(f) + var f_time = path.last_modified(f_prefix) - if is_bytecode + if suffix_bec if f_time == nil return false end # file does not exist # f is the right file, continue else @@ -348,13 +368,20 @@ class Tasmota # bytecode exists and is more recent than berry source, use bytecode ##### temporarily disable loading from bec file # f = f + "c" # use bytecode name - is_bytecode = true + suffix_bec = true end end + # recall the working directory + if f_archive + self.wd = f_prefix + "#" + else + self.wd = "" + end + var c = compile(f, 'file') # save the compiled bytecode - if !is_bytecode + if !suffix_bec && !f_archive try self.save(f + 'c', c) except .. as e diff --git a/lib/libesp32/Berry/default/embedded/autoconf.be b/lib/libesp32/Berry/default/embedded/autoconf.be new file mode 100644 index 000000000..3be35fe1e --- /dev/null +++ b/lib/libesp32/Berry/default/embedded/autoconf.be @@ -0,0 +1,387 @@ +#- autocong module for Berry -# +#- -# +#- To solidify: -# +#- + # load only persis_module and persist_module.init + import autoconf + solidify.dump(autoconf_module) + # copy and paste into `be_autoconf_lib.c` +-# +#- + +# For external compile: + +display = module("display") +self = nil +tasmota = nil +def load() end + +-# + +var autoconf_module = module("autoconf") + +autoconf_module.init = def (m) + + class Autoconf + var _archive + var _error + + def init() + import path + import string + + var dir = path.listdir("/") + var entry + tasmota.add_driver(self) + + var i = 0 + while i < size(dir) + if string.find(dir[i], "_autoconf.zip") > 0 # does the file contain '*_autoconf.zip' + if entry != nil + # we have multiple configuration files, not allowed + print(string.format("CFG: multiple autoconf files found, aborting ('%s' + '%s')", entry, dir[i])) + self._error = true + return nil + end + entry = dir[i] + end + i += 1 + end + + if entry == nil + print("CFG: no '*_autoconf.zip' file found") + return nil + end + + self._archive = entry + end + + + # #################################################################################################### + # Manage first time marker + # #################################################################################################### + def is_first_time() + import path + return !path.exists("/.autoconf") + end + def set_first_time() + var f = open("/.autoconf", "w") + f.close() + end + def clear_first_time() + import path + path.remove("/.autoconf") + end + + # #################################################################################################### + # Delete all autoconfig files present + # #################################################################################################### + def delete_all_configs() + import path + import string + var dir = path.listdir("/") + + for d:dir + if string.find(d, "_autoconf.zip") > 0 # does the file contain '*_autoconf.zip' + path.remove(d) + end + end + end + + # #################################################################################################### + # Get current module + # contains the name of the archive without leading `/`, ex: `M5Stack_Fire_autoconf.zip` + # or `nil` if none + # #################################################################################################### + def get_current_module_path() + return self._archive + end + def get_current_module_name() + return self._archive[0..-13] + end + + # #################################################################################################### + # Load templates from Github + # #################################################################################################### + def load_templates() + import string + import json + try + var url = string.format("https://raw.githubusercontent.com/tasmota/autoconf/main/%s_manifest.json", tasmota.arch()) + tasmota.log(string.format("CFG: loading '%s'", url), 3) + # load the template + var cl = webclient() + cl.begin(url) + var r = cl.GET() + if r != 200 + tasmota.log(string.format("CFG: return_code=%i", r), 2) + return nil + end + var s = cl.get_string() + cl.close() + # convert to json + var j = json.load(s) + tasmota.log(string.format("CFG: loaded '%s'", str(j)), 3) + + var t = j.find("zip") + if isinstance(t, list) + return t + end + + return nil + except .. as e, m + tasmota.log(string.format("CFG: exception '%s' - '%s'", e, m), 2) + return nil + end + end + + # #################################################################################################### + # Init web handlers + # #################################################################################################### + # Displays a "Autocong" button on the configuration page + def web_add_config_button() + import webserver + webserver.content_send("

") + end + + + # This HTTP GET manager controls which web controls are displayed + def page_autoconf_mgr() + import webserver + import string + if !webserver.check_privileged_access() return nil end + + webserver.content_start('Auto-configuration') + webserver.content_send_style() + webserver.content_send("

 (This feature requires an internet connection)

") + + var cur_module = self.get_current_module_path() + var cur_module_display = cur_module ? string.tr(self.get_current_module_path(), "_", " ") : self._error ? "<Error: apply new or remove>" : "<None>" + + webserver.content_send("
") + webserver.content_send(string.format(" Current auto-configuration")) + webserver.content_send(string.format("

Current configuration:

%s

", cur_module_display)) + + if cur_module + # add button to reapply template + webserver.content_send("

") + webserver.content_send("") + webserver.content_send("

") + end + webserver.content_send("

") + + webserver.content_send("
") + webserver.content_send(string.format(" Select new auto-configuration")) + + webserver.content_send("

") + webserver.content_send("
") + webserver.content_send("

") + + webserver.content_send("") + # webserver.content_send(string.format("", ota_num)) + webserver.content_send("

") + + + webserver.content_send("

") + webserver.content_button(webserver.BUTTON_CONFIGURATION) + webserver.content_stop() + end + + # #################################################################################################### + # Web controller + # + # Applies the changes and restart + # #################################################################################################### + # This HTTP POST manager handles the submitted web form data + def page_autoconf_ctl() + import webserver + import string + import path + if !webserver.check_privileged_access() return nil end + + try + if webserver.has_arg("reapply") + tasmota.log("CFG: removing first time marker", 2); + # print("CFG: removing first time marker") + self.clear_first_time() + #- and force restart -# + webserver.redirect("/?rst=") + + elif webserver.has_arg("zip") + # remove any remaining autoconf file + tasmota.log("CFG: removing autoconf files", 2); + # print("CFG: removing autoconf files") + self.delete_all_configs() + + # get the name of the configuration file + var arch_name = webserver.arg("zip") + + if arch_name != "reset" + var url = string.format("https://raw.githubusercontent.com/tasmota/autoconf/main/%s/%s_autoconf.zip", tasmota.arch(), arch_name) + tasmota.log(string.format("CFG: downloading '%s'", url), 2); + + var local_file = string.format("%s_autoconf.zip", arch_name) + + # download file and write directly to file system + var cl = webclient() + cl.begin(url) + var r = cl.GET() + if r != 200 raise "connection_error", string.format("return code=%i", r) end + cl.write_file(local_file) + cl.close() + end + + # remove marker to reapply template + self.clear_first_time() + + #- and force restart -# + webserver.redirect("/?rst=") + else + raise "value_error", "Unknown command" + end + except .. as e, m + print(string.format("CFG: Exception> '%s' - %s", e, m)) + #- display error page -# + webserver.content_start("Parameter error") #- title of the web page -# + webserver.content_send_style() #- send standard Tasmota styles -# + + webserver.content_send(string.format("

Exception:
'%s'
%s

", e, m)) + + webserver.content_button(webserver.BUTTON_CONFIGURATION) #- button back to management page -# + webserver.content_stop() #- end of web page -# + end + end + + # Add HTTP POST and GET handlers + def web_add_handler() + import webserver + webserver.on('/ac', / -> self.page_autoconf_mgr(), webserver.HTTP_GET) + webserver.on('/ac', / -> self.page_autoconf_ctl(), webserver.HTTP_POST) + end + + + # reset the configuration information (but don't restart) + # i.e. remove any autoconf file + def reset() + import path + import string + + var dir = path.listdir("/") + var entry + + var i = 0 + while i < size(dir) + var fname = dir[i] + if string.find(fname, "_autoconf.zip") > 0 # does the file contain '*_autoconf.zip' + path.remove(fname) + print(string.format("CFG: removed file '%s'", fname)) + end + i += 1 + end + + self._archive = nil + self._error = nil + end + + def preinit() + if self._archive == nil return end + # try to launch `preinit.be` + import path + + var fname = self._archive + '#preinit.be' + if path.exists(fname) + tasmota.log("CFG: loading "+fname, 3) + load(fname) + tasmota.log("CFG: loaded "+fname, 3) + end + end + + def run_bat(fname) # read a '*.bat' file and run each command + import string + var f + try + f = open(fname, "r") # open file in read-only mode, it is expected to exist + while true + var line = f.readline() # read each line, can contain a terminal '\n', empty if end of file + if size(line) == 0 break end # end of file + + if line[-1] == "\n" line = line[0..-2] end # remove any trailing '\n' + if size(line) > 0 + tasmota.cmd(line) # run the command + end + end + f.close() # close, we don't expect exception with read-only, could be added later though + except .. as e, m + print(string.format('CFG: could not run %s (%s - %s)', fname, e, m)) + f.close() + end + end + + def autoexec() + if self._archive == nil return end + # try to launch `preinit.be` + import path + + # Step 1. if first run, only apply `init.bat` + var fname = self._archive + '#init.bat' + if self.is_first_time() && path.exists(fname) + # create the '.autoconf' file to avoid running it again, even if it crashed + self.set_first_time() + + # if path.exists(fname) # we know it exists from initial test + self.run_bat(fname) + tasmota.log("CFG: 'init.bat' done, restarting", 2) + tasmota.cmd("Restart 1") + return # if init was run, force a restart anyways and don't run the remaining code + # end + end + + # Step 2. if 'display.ini' is present, launch Universal Display + fname = self._archive + '#display.ini' + if gpio.pin_used(gpio.OPTION_A, 2) && path.exists(fname) + if path.exists("display.ini") + tasmota.log("CFG: skipping 'display.ini' because already present in file-system", 2) + else + import display + var f = open(fname,"r") + var desc = f.read() + f.close() + display.start(desc) + end + end + + # Step 3. if 'autoexec.bat' is present, run it + fname = self._archive + '#autoexec.bat' + if path.exists(fname) + tasmota.log("CFG: running "+fname, 3) + self.run_bat(fname) + tasmota.log("CFG: ran "+fname, 3) + end + + # Step 4. if 'autoexec.be' is present, load it + fname = self._archive + '#autoexec.be' + if path.exists(fname) + tasmota.log("CFG: loading "+fname, 3) + load(fname) + tasmota.log("CFG: loaded "+fname, 3) + end + end + end + + return Autoconf() # return an instance of this class +end + +aa = autoconf_module.init(autoconf_module) +import webserver +webserver.on('/ac2', / -> aa.page_autoconf_mgr(), webserver.HTTP_GET) +return autoconf_module diff --git a/lib/libesp32/Berry/generate/be_const_strtab.h b/lib/libesp32/Berry/generate/be_const_strtab.h index aaf1a94a3..c9aafc561 100644 --- a/lib/libesp32/Berry/generate/be_const_strtab.h +++ b/lib/libesp32/Berry/generate/be_const_strtab.h @@ -1,343 +1,346 @@ -extern const bcstring be_const_str_SERIAL_5N1; -extern const bcstring be_const_str__global_addr; extern const bcstring be_const_str_setmember; -extern const bcstring be_const_str_OneWire; -extern const bcstring be_const_str__get_cb; -extern const bcstring be_const_str_classof; -extern const bcstring be_const_str_SERIAL_8O2; -extern const bcstring be_const_str___upper__; -extern const bcstring be_const_str_gamma10; -extern const bcstring be_const_str_copy; -extern const bcstring be_const_str_tostring; -extern const bcstring be_const_str_dot_p1; -extern const bcstring be_const_str_item; -extern const bcstring be_const_str_read8; -extern const bcstring be_const_str_setbits; -extern const bcstring be_const_str_upper; -extern const bcstring be_const_str_rad; -extern const bcstring be_const_str_web_send; -extern const bcstring be_const_str_load; -extern const bcstring be_const_str_opt_add; extern const bcstring be_const_str_hex; -extern const bcstring be_const_str_read12; -extern const bcstring be_const_str_end; -extern const bcstring be_const_str_chars_in_string; -extern const bcstring be_const_str_write8; -extern const bcstring be_const_str_def; -extern const bcstring be_const_str_select; -extern const bcstring be_const_str_type; -extern const bcstring be_const_str_global; -extern const bcstring be_const_str_yield; -extern const bcstring be_const_str_opt_eq; -extern const bcstring be_const_str_SERIAL_8E1; -extern const bcstring be_const_str_rtc; -extern const bcstring be_const_str_else; -extern const bcstring be_const_str_get_power; -extern const bcstring be_const_str_addr; -extern const bcstring be_const_str_allocated; -extern const bcstring be_const_str_finish; -extern const bcstring be_const_str_dot_p; -extern const bcstring be_const_str_getbits; -extern const bcstring be_const_str_tag; -extern const bcstring be_const_str_add; -extern const bcstring be_const_str_pin; -extern const bcstring be_const_str_set_timeouts; -extern const bcstring be_const_str_import; -extern const bcstring be_const_str_SERIAL_6N1; -extern const bcstring be_const_str_SERIAL_8O1; -extern const bcstring be_const_str__settings_ptr; -extern const bcstring be_const_str_remove_cmd; -extern const bcstring be_const_str___iterator__; -extern const bcstring be_const_str_atan2; -extern const bcstring be_const_str_ctypes_bytes; -extern const bcstring be_const_str_millis; -extern const bcstring be_const_str_available; -extern const bcstring be_const_str_delay; -extern const bcstring be_const_str_imin; -extern const bcstring be_const_str_shared_key; -extern const bcstring be_const_str_wire; -extern const bcstring be_const_str__drivers; -extern const bcstring be_const_str_last_modified; -extern const bcstring be_const_str_serial; -extern const bcstring be_const_str_opt_call; -extern const bcstring be_const_str_webclient; -extern const bcstring be_const_str_SERIAL_6E2; -extern const bcstring be_const_str_ctypes_bytes_dyn; -extern const bcstring be_const_str_time_dump; -extern const bcstring be_const_str_static; -extern const bcstring be_const_str_classname; -extern const bcstring be_const_str_isrunning; -extern const bcstring be_const_str_top; -extern const bcstring be_const_str_remove; -extern const bcstring be_const_str_begin; -extern const bcstring be_const_str_content_stop; -extern const bcstring be_const_str_deg; -extern const bcstring be_const_str_gc; -extern const bcstring be_const_str_gen_cb; -extern const bcstring be_const_str_reset; -extern const bcstring be_const_str_clear; -extern const bcstring be_const_str_skip; -extern const bcstring be_const_str_SERIAL_5E1; -extern const bcstring be_const_str_has; -extern const bcstring be_const_str_raise; -extern const bcstring be_const_str_setitem; -extern const bcstring be_const_str_write_bit; -extern const bcstring be_const_str_stop; -extern const bcstring be_const_str_AES_GCM; -extern const bcstring be_const_str_exec_cmd; -extern const bcstring be_const_str_iter; -extern const bcstring be_const_str_ceil; -extern const bcstring be_const_str_exp; -extern const bcstring be_const_str_tob64; -extern const bcstring be_const_str_wire_scan; -extern const bcstring be_const_str_call; -extern const bcstring be_const_str_cmd_res; -extern const bcstring be_const_str_opt_connect; +extern const bcstring be_const_str_arch; extern const bcstring be_const_str_resolvecmnd; -extern const bcstring be_const_str_SERIAL_6E1; -extern const bcstring be_const_str_try; -extern const bcstring be_const_str__cb; -extern const bcstring be_const_str_AudioOutput; -extern const bcstring be_const_str_check_privileged_access; -extern const bcstring be_const_str_SERIAL_6O2; -extern const bcstring be_const_str_content_send; -extern const bcstring be_const_str_tolower; -extern const bcstring be_const_str_detect; -extern const bcstring be_const_str_imax; -extern const bcstring be_const_str_set_auth; -extern const bcstring be_const_str_depower; -extern const bcstring be_const_str_read24; -extern const bcstring be_const_str_add_header; -extern const bcstring be_const_str_kv; -extern const bcstring be_const_str_pin_used; -extern const bcstring be_const_str_publish_result; -extern const bcstring be_const_str_do; -extern const bcstring be_const_str_pow; -extern const bcstring be_const_str_read_bytes; -extern const bcstring be_const_str_SERIAL_5E2; -extern const bcstring be_const_str_scale_uint; -extern const bcstring be_const_str_get; -extern const bcstring be_const_str_remove_timer; -extern const bcstring be_const_str_dot_len; -extern const bcstring be_const_str_Wire; -extern const bcstring be_const_str__begin_transmission; -extern const bcstring be_const_str_toupper; -extern const bcstring be_const_str_SERIAL_5N2; -extern const bcstring be_const_str_arg_size; -extern const bcstring be_const_str_AudioFileSource; -extern const bcstring be_const_str_I2C_Driver; -extern const bcstring be_const_str_decrypt; -extern const bcstring be_const_str_digital_write; -extern const bcstring be_const_str_input; -extern const bcstring be_const_str_char; -extern const bcstring be_const_str_floor; -extern const bcstring be_const_str_real; -extern const bcstring be_const_str_AudioGenerator; -extern const bcstring be_const_str__cmd; -extern const bcstring be_const_str_enabled; -extern const bcstring be_const_str_int; -extern const bcstring be_const_str_byte; -extern const bcstring be_const_str_resp_cmnd_error; -extern const bcstring be_const_str_dot_size; -extern const bcstring be_const_str_list; -extern const bcstring be_const_str_reset_search; -extern const bcstring be_const_str_SERIAL_7N2; -extern const bcstring be_const_str_set; -extern const bcstring be_const_str_elif; -extern const bcstring be_const_str_Tasmota; -extern const bcstring be_const_str_get_switch; -extern const bcstring be_const_str_read; -extern const bcstring be_const_str___lower__; -extern const bcstring be_const_str__read; -extern const bcstring be_const_str_asin; -extern const bcstring be_const_str_POST; -extern const bcstring be_const_str_arg; -extern const bcstring be_const_str_reduce; -extern const bcstring be_const_str_deinit; -extern const bcstring be_const_str_save; -extern const bcstring be_const_str_SERIAL_8E2; -extern const bcstring be_const_str_get_size; -extern const bcstring be_const_str_search; -extern const bcstring be_const_str_srand; -extern const bcstring be_const_str_isnan; +extern const bcstring be_const_str_resp_cmnd_done; +extern const bcstring be_const_str_top; +extern const bcstring be_const_str_content_start; +extern const bcstring be_const_str_deg; +extern const bcstring be_const_str_fromptr; +extern const bcstring be_const_str_time_dump; +extern const bcstring be_const_str_compile; +extern const bcstring be_const_str_members; extern const bcstring be_const_str_arg_name; -extern const bcstring be_const_str_content_flush; -extern const bcstring be_const_str_get_light; -extern const bcstring be_const_str_sqrt; -extern const bcstring be_const_str__end_transmission; -extern const bcstring be_const_str_listdir; -extern const bcstring be_const_str_log10; +extern const bcstring be_const_str_real; +extern const bcstring be_const_str_insert; +extern const bcstring be_const_str_open; +extern const bcstring be_const_str_ctypes_bytes; +extern const bcstring be_const_str_tag; +extern const bcstring be_const_str_reset; +extern const bcstring be_const_str_toupper; +extern const bcstring be_const_str_POST; +extern const bcstring be_const_str_SERIAL_6O2; +extern const bcstring be_const_str_iter; +extern const bcstring be_const_str_load; +extern const bcstring be_const_str_available; +extern const bcstring be_const_str_ceil; +extern const bcstring be_const_str_clear; +extern const bcstring be_const_str_digital_read; +extern const bcstring be_const_str__get_cb; +extern const bcstring be_const_str_bytes; +extern const bcstring be_const_str_settings; +extern const bcstring be_const_str_get_string; +extern const bcstring be_const_str_asstring; +extern const bcstring be_const_str_pin_used; extern const bcstring be_const_str_pop; -extern const bcstring be_const_str_read32; -extern const bcstring be_const_str_for; -extern const bcstring be_const_str_exec_tele; +extern const bcstring be_const_str_static; +extern const bcstring be_const_str_AES_GCM; +extern const bcstring be_const_str_SERIAL_8N2; +extern const bcstring be_const_str_close; +extern const bcstring be_const_str_set_power; +extern const bcstring be_const_str_find_op; +extern const bcstring be_const_str_get; +extern const bcstring be_const_str_print; +extern const bcstring be_const_str_publish_result; +extern const bcstring be_const_str_target_search; +extern const bcstring be_const_str__ccmd; +extern const bcstring be_const_str_fromb64; +extern const bcstring be_const_str_module; +extern const bcstring be_const_str_allocated; +extern const bcstring be_const_str_GET; +extern const bcstring be_const_str_SERIAL_8E1; +extern const bcstring be_const_str_classof; +extern const bcstring be_const_str_cos; +extern const bcstring be_const_str_assert; +extern const bcstring be_const_str_content_send; +extern const bcstring be_const_str_read13; +extern const bcstring be_const_str_reverse; +extern const bcstring be_const_str_set_timer; +extern const bcstring be_const_str_class; +extern const bcstring be_const_str_codedump; +extern const bcstring be_const_str_isrunning; +extern const bcstring be_const_str_publish; +extern const bcstring be_const_str_range; +extern const bcstring be_const_str_write; +extern const bcstring be_const_str_opt_connect; +extern const bcstring be_const_str_SERIAL_7O1; +extern const bcstring be_const_str_update; +extern const bcstring be_const_str__cmd; +extern const bcstring be_const_str_isnan; +extern const bcstring be_const_str_resp_cmnd_failed; +extern const bcstring be_const_str_SERIAL_5O1; +extern const bcstring be_const_str_abs; +extern const bcstring be_const_str_SERIAL_7E2; +extern const bcstring be_const_str_SERIAL_6N1; +extern const bcstring be_const_str__cb; +extern const bcstring be_const_str_depower; +extern const bcstring be_const_str_Tasmota; +extern const bcstring be_const_str_item; +extern const bcstring be_const_str_set_useragent; +extern const bcstring be_const_str_wire2; +extern const bcstring be_const_str_time_reached; +extern const bcstring be_const_str_chars_in_string; +extern const bcstring be_const_str_false; +extern const bcstring be_const_str_add_rule; +extern const bcstring be_const_str_setbits; +extern const bcstring be_const_str_write_file; +extern const bcstring be_const_str_SERIAL_8O1; +extern const bcstring be_const_str_wd; +extern const bcstring be_const_str_wire_scan; +extern const bcstring be_const_str_AudioFileSourceFS; +extern const bcstring be_const_str_get_free_heap; +extern const bcstring be_const_str_AudioGenerator; +extern const bcstring be_const_str_SERIAL_5E2; +extern const bcstring be_const_str__global_addr; +extern const bcstring be_const_str_content_send_style; +extern const bcstring be_const_str_remove_timer; +extern const bcstring be_const_str_tr; +extern const bcstring be_const_str_dot_w; +extern const bcstring be_const_str_MD5; +extern const bcstring be_const_str_break; +extern const bcstring be_const_str_digital_write; +extern const bcstring be_const_str_asin; +extern const bcstring be_const_str__def; +extern const bcstring be_const_str_exec_cmd; +extern const bcstring be_const_str_exists; +extern const bcstring be_const_str_flush; +extern const bcstring be_const_str_as; +extern const bcstring be_const_str_set_light; +extern const bcstring be_const_str_time_str; +extern const bcstring be_const_str_arg_size; +extern const bcstring be_const_str_bus; +extern const bcstring be_const_str_opt_eq; +extern const bcstring be_const_str_try_rule; +extern const bcstring be_const_str_kv; +extern const bcstring be_const_str_reverse_gamma10; +extern const bcstring be_const_str_tostring; +extern const bcstring be_const_str_format; +extern const bcstring be_const_str_tob64; +extern const bcstring be_const_str_continue; extern const bcstring be_const_str_log; +extern const bcstring be_const_str_SERIAL_7N1; +extern const bcstring be_const_str_lower; +extern const bcstring be_const_str_stop; +extern const bcstring be_const_str_count; +extern const bcstring be_const_str_encrypt; +extern const bcstring be_const_str_resp_cmnd_str; +extern const bcstring be_const_str_byte; +extern const bcstring be_const_str_fromstring; +extern const bcstring be_const_str_run_deferred; +extern const bcstring be_const_str_setitem; +extern const bcstring be_const_str_cmd; +extern const bcstring be_const_str_event; +extern const bcstring be_const_str_SERIAL_6E1; +extern const bcstring be_const_str_SERIAL_6O1; +extern const bcstring be_const_str_remove_driver; +extern const bcstring be_const_str_EC_C25519; +extern const bcstring be_const_str_read12; +extern const bcstring be_const_str__write; +extern const bcstring be_const_str_opt_call; +extern const bcstring be_const_str_AudioOutput; +extern const bcstring be_const_str_attrdump; +extern const bcstring be_const_str_int; +extern const bcstring be_const_str_AudioGeneratorMP3; +extern const bcstring be_const_str_add_header; +extern const bcstring be_const_str_ctypes_bytes_dyn; +extern const bcstring be_const_str_keys; +extern const bcstring be_const_str_set_auth; +extern const bcstring be_const_str_def; +extern const bcstring be_const_str_; +extern const bcstring be_const_str_SERIAL_5N2; +extern const bcstring be_const_str__rules; +extern const bcstring be_const_str_has; +extern const bcstring be_const_str_set; +extern const bcstring be_const_str_public_key; +extern const bcstring be_const_str_get_power; +extern const bcstring be_const_str_type; +extern const bcstring be_const_str_opt_add; +extern const bcstring be_const_str_dot_size; +extern const bcstring be_const_str_set_timeouts; +extern const bcstring be_const_str_tomap; +extern const bcstring be_const_str_getbits; +extern const bcstring be_const_str_sinh; +extern const bcstring be_const_str_sqrt; +extern const bcstring be_const_str_dot_p1; +extern const bcstring be_const_str_begin; +extern const bcstring be_const_str_delay; +extern const bcstring be_const_str_scan; +extern const bcstring be_const_str_for; +extern const bcstring be_const_str_read8; +extern const bcstring be_const_str_AudioGeneratorWAV; +extern const bcstring be_const_str_get_light; +extern const bcstring be_const_str__global_def; extern const bcstring be_const_str_map; extern const bcstring be_const_str_redirect; -extern const bcstring be_const_str_format; -extern const bcstring be_const_str_pi; -extern const bcstring be_const_str_range; -extern const bcstring be_const_str_SERIAL_7E2; -extern const bcstring be_const_str_count; -extern const bcstring be_const_str_update; -extern const bcstring be_const_str_SERIAL_7N1; -extern const bcstring be_const_str_find_key_i; -extern const bcstring be_const_str_content_button; -extern const bcstring be_const_str_AudioGeneratorMP3; -extern const bcstring be_const_str_AudioGeneratorWAV; -extern const bcstring be_const_str__buffer; -extern const bcstring be_const_str_remove_driver; -extern const bcstring be_const_str_false; -extern const bcstring be_const_str_fromptr; -extern const bcstring be_const_str_geti; -extern const bcstring be_const_str_lower; -extern const bcstring be_const_str_nan; -extern const bcstring be_const_str_assert; -extern const bcstring be_const_str_time_str; -extern const bcstring be_const_str_exists; -extern const bcstring be_const_str_read13; -extern const bcstring be_const_str_set_power; -extern const bcstring be_const_str_seti; -extern const bcstring be_const_str_toptr; -extern const bcstring be_const_str_acos; -extern const bcstring be_const_str_find_op; +extern const bcstring be_const_str__ptr; extern const bcstring be_const_str_isinstance; -extern const bcstring be_const_str_cb_dispatch; -extern const bcstring be_const_str_SERIAL_5O2; -extern const bcstring be_const_str_bytes; -extern const bcstring be_const_str_public_key; -extern const bcstring be_const_str_continue; -extern const bcstring be_const_str_; -extern const bcstring be_const_str__available; -extern const bcstring be_const_str__def; -extern const bcstring be_const_str_i2c_enabled; -extern const bcstring be_const_str_reverse; -extern const bcstring be_const_str_true; -extern const bcstring be_const_str_dac_voltage; -extern const bcstring be_const_str_name; -extern const bcstring be_const_str_reverse_gamma10; -extern const bcstring be_const_str_add_rule; -extern const bcstring be_const_str_dump; -extern const bcstring be_const_str_AudioOutputI2S; -extern const bcstring be_const_str_attrdump; -extern const bcstring be_const_str_fromstring; -extern const bcstring be_const_str_publish; -extern const bcstring be_const_str_wifi; -extern const bcstring be_const_str__write; -extern const bcstring be_const_str_resp_cmnd; -extern const bcstring be_const_str_tomap; -extern const bcstring be_const_str_content_start; -extern const bcstring be_const_str_traceback; -extern const bcstring be_const_str_as; -extern const bcstring be_const_str_memory; -extern const bcstring be_const_str_pin_mode; -extern const bcstring be_const_str_EC_C25519; -extern const bcstring be_const_str_str; -extern const bcstring be_const_str_tanh; -extern const bcstring be_const_str_write_bytes; -extern const bcstring be_const_str_except; -extern const bcstring be_const_str_get_option; -extern const bcstring be_const_str_dot_w; -extern const bcstring be_const_str_SERIAL_7O1; -extern const bcstring be_const_str_SERIAL_8N1; -extern const bcstring be_const_str_init; -extern const bcstring be_const_str__timers; -extern const bcstring be_const_str_super; -extern const bcstring be_const_str_GET; -extern const bcstring be_const_str_fromb64; -extern const bcstring be_const_str_break; -extern const bcstring be_const_str__global_def; -extern const bcstring be_const_str_bus; -extern const bcstring be_const_str_find; -extern const bcstring be_const_str_resp_cmnd_failed; -extern const bcstring be_const_str_SERIAL_6N2; -extern const bcstring be_const_str__request_from; -extern const bcstring be_const_str_cos; -extern const bcstring be_const_str_cosh; -extern const bcstring be_const_str_set_useragent; +extern const bcstring be_const_str_pin; extern const bcstring be_const_str_size; -extern const bcstring be_const_str_web_send_decimal; -extern const bcstring be_const_str_write; -extern const bcstring be_const_str_module; -extern const bcstring be_const_str_try_rule; -extern const bcstring be_const_str_var; -extern const bcstring be_const_str_content_send_style; -extern const bcstring be_const_str_sinh; +extern const bcstring be_const_str_state; +extern const bcstring be_const_str_dot_p; +extern const bcstring be_const_str__drivers; +extern const bcstring be_const_str_erase; +extern const bcstring be_const_str_I2C_Driver; +extern const bcstring be_const_str_addr; +extern const bcstring be_const_str_copy; +extern const bcstring be_const_str_find_key_i; +extern const bcstring be_const_str_pin_mode; +extern const bcstring be_const_str_setrange; +extern const bcstring be_const_str_SERIAL_8N1; +extern const bcstring be_const_str_char; +extern const bcstring be_const_str_concat; +extern const bcstring be_const_str_remove; +extern const bcstring be_const_str_serial; +extern const bcstring be_const_str_SERIAL_5O2; +extern const bcstring be_const_str__read; +extern const bcstring be_const_str_cmd_res; +extern const bcstring be_const_str_contains; +extern const bcstring be_const_str_imax; +extern const bcstring be_const_str_super; +extern const bcstring be_const_str_try; +extern const bcstring be_const_str_last_modified; extern const bcstring be_const_str_return; -extern const bcstring be_const_str_asstring; -extern const bcstring be_const_str_digital_read; -extern const bcstring be_const_str_has_arg; -extern const bcstring be_const_str_number; -extern const bcstring be_const_str_remove_rule; -extern const bcstring be_const_str_get_string; +extern const bcstring be_const_str_SERIAL_6N2; +extern const bcstring be_const_str_call; extern const bcstring be_const_str_resize; -extern const bcstring be_const_str_encrypt; -extern const bcstring be_const_str_opt_neq; -extern const bcstring be_const_str_add_driver; -extern const bcstring be_const_str_close; +extern const bcstring be_const_str_escape; +extern const bcstring be_const_str_upper; +extern const bcstring be_const_str_end; +extern const bcstring be_const_str_gamma8; +extern const bcstring be_const_str_memory; +extern const bcstring be_const_str_wifi; +extern const bcstring be_const_str_yield; +extern const bcstring be_const_str_get_option; +extern const bcstring be_const_str_init; +extern const bcstring be_const_str_read; +extern const bcstring be_const_str__settings_ptr; +extern const bcstring be_const_str__timers; +extern const bcstring be_const_str_finish; +extern const bcstring be_const_str___upper__; +extern const bcstring be_const_str_dump; +extern const bcstring be_const_str_save; +extern const bcstring be_const_str___lower__; +extern const bcstring be_const_str_listdir; +extern const bcstring be_const_str_check_privileged_access; +extern const bcstring be_const_str_rand; +extern const bcstring be_const_str_web_send; +extern const bcstring be_const_str_i2c_enabled; +extern const bcstring be_const_str_wire1; +extern const bcstring be_const_str_dac_voltage; +extern const bcstring be_const_str_imin; +extern const bcstring be_const_str_log10; +extern const bcstring be_const_str_skip; +extern const bcstring be_const_str_else; +extern const bcstring be_const_str_except; +extern const bcstring be_const_str_nil; +extern const bcstring be_const_str_resp_cmnd_error; +extern const bcstring be_const_str_calldepth; +extern const bcstring be_const_str_do; +extern const bcstring be_const_str___iterator__; +extern const bcstring be_const_str_true; +extern const bcstring be_const_str_rad; +extern const bcstring be_const_str_import; +extern const bcstring be_const_str_SERIAL_8O2; +extern const bcstring be_const_str_gamma10; +extern const bcstring be_const_str_elif; +extern const bcstring be_const_str_resp_cmnd; +extern const bcstring be_const_str_shared_key; +extern const bcstring be_const_str_web_send_decimal; +extern const bcstring be_const_str_write8; +extern const bcstring be_const_str_SERIAL_5E1; extern const bcstring be_const_str_member; -extern const bcstring be_const_str_response_append; +extern const bcstring be_const_str_sin; +extern const bcstring be_const_str_OneWire; +extern const bcstring be_const_str_SERIAL_7O2; +extern const bcstring be_const_str__begin_transmission; +extern const bcstring be_const_str_get_switch; +extern const bcstring be_const_str_name; +extern const bcstring be_const_str_nan; +extern const bcstring be_const_str_add; +extern const bcstring be_const_str_eth; +extern const bcstring be_const_str_find; +extern const bcstring be_const_str_read32; +extern const bcstring be_const_str_remove_cmd; +extern const bcstring be_const_str_gc; +extern const bcstring be_const_str_reset_search; +extern const bcstring be_const_str_content_stop; +extern const bcstring be_const_str_counters; +extern const bcstring be_const_str_detect; +extern const bcstring be_const_str_exp; +extern const bcstring be_const_str_on; +extern const bcstring be_const_str_arg; +extern const bcstring be_const_str_reduce; extern const bcstring be_const_str_split; extern const bcstring be_const_str_strftime; -extern const bcstring be_const_str_exec_rules; -extern const bcstring be_const_str_AudioFileSourceFS; -extern const bcstring be_const_str__ccmd; -extern const bcstring be_const_str_set_timer; -extern const bcstring be_const_str_time_reached; -extern const bcstring be_const_str_SERIAL_7O2; -extern const bcstring be_const_str_SERIAL_8N2; +extern const bcstring be_const_str_raise; +extern const bcstring be_const_str_AudioOutputI2S; extern const bcstring be_const_str_if; -extern const bcstring be_const_str__ptr; -extern const bcstring be_const_str_insert; -extern const bcstring be_const_str_print; -extern const bcstring be_const_str_run_deferred; -extern const bcstring be_const_str_scan; -extern const bcstring be_const_str_settings; -extern const bcstring be_const_str_arch; -extern const bcstring be_const_str_open; -extern const bcstring be_const_str_cmd; -extern const bcstring be_const_str_loop; -extern const bcstring be_const_str_wire1; -extern const bcstring be_const_str_nil; -extern const bcstring be_const_str_SERIAL_7E1; -extern const bcstring be_const_str_keys; -extern const bcstring be_const_str_sin; -extern const bcstring be_const_str_calldepth; -extern const bcstring be_const_str_while; -extern const bcstring be_const_str_counters; -extern const bcstring be_const_str_members; -extern const bcstring be_const_str_on; -extern const bcstring be_const_str__rules; -extern const bcstring be_const_str_collect; -extern const bcstring be_const_str_url_encode; -extern const bcstring be_const_str_codedump; -extern const bcstring be_const_str_dot_p2; -extern const bcstring be_const_str_MD5; +extern const bcstring be_const_str_cb_dispatch; +extern const bcstring be_const_str_exec_tele; +extern const bcstring be_const_str_srand; +extern const bcstring be_const_str_write_bytes; extern const bcstring be_const_str__settings_def; -extern const bcstring be_const_str_erase; -extern const bcstring be_const_str_gamma8; -extern const bcstring be_const_str_rand; -extern const bcstring be_const_str_resp_cmnd_str; -extern const bcstring be_const_str_state; -extern const bcstring be_const_str_SERIAL_6O1; -extern const bcstring be_const_str_contains; -extern const bcstring be_const_str_set_light; -extern const bcstring be_const_str_setrange; -extern const bcstring be_const_str_tan; -extern const bcstring be_const_str_target_search; -extern const bcstring be_const_str_abs; -extern const bcstring be_const_str_resp_cmnd_done; -extern const bcstring be_const_str_eth; -extern const bcstring be_const_str_SERIAL_5O1; -extern const bcstring be_const_str_concat; -extern const bcstring be_const_str_flush; -extern const bcstring be_const_str_get_free_heap; -extern const bcstring be_const_str_push; -extern const bcstring be_const_str_compile; -extern const bcstring be_const_str_wire2; +extern const bcstring be_const_str_cosh; +extern const bcstring be_const_str_pi; +extern const bcstring be_const_str_remove_rule; +extern const bcstring be_const_str_scale_uint; +extern const bcstring be_const_str_var; +extern const bcstring be_const_str_SERIAL_8E2; +extern const bcstring be_const_str_acos; +extern const bcstring be_const_str_gen_cb; +extern const bcstring be_const_str_read_bytes; +extern const bcstring be_const_str_AudioFileSource; +extern const bcstring be_const_str_SERIAL_5N1; +extern const bcstring be_const_str_wire; +extern const bcstring be_const_str_while; +extern const bcstring be_const_str_SERIAL_7N2; +extern const bcstring be_const_str_get_size; +extern const bcstring be_const_str_exec_rules; +extern const bcstring be_const_str__available; +extern const bcstring be_const_str_search; +extern const bcstring be_const_str_global; +extern const bcstring be_const_str_collect; +extern const bcstring be_const_str_input; +extern const bcstring be_const_str_response_append; +extern const bcstring be_const_str_str; +extern const bcstring be_const_str_SERIAL_6E2; +extern const bcstring be_const_str_SERIAL_7E1; +extern const bcstring be_const_str_content_button; +extern const bcstring be_const_str_number; +extern const bcstring be_const_str_tanh; +extern const bcstring be_const_str_toptr; +extern const bcstring be_const_str_write_bit; extern const bcstring be_const_str_add_cmd; +extern const bcstring be_const_str_select; +extern const bcstring be_const_str_traceback; +extern const bcstring be_const_str_atan2; +extern const bcstring be_const_str_loop; +extern const bcstring be_const_str_millis; +extern const bcstring be_const_str_url_encode; +extern const bcstring be_const_str__end_transmission; +extern const bcstring be_const_str_deinit; +extern const bcstring be_const_str_tan; +extern const bcstring be_const_str_geti; +extern const bcstring be_const_str_seti; +extern const bcstring be_const_str__buffer; extern const bcstring be_const_str_atan; -extern const bcstring be_const_str_event; +extern const bcstring be_const_str_content_flush; +extern const bcstring be_const_str_list; +extern const bcstring be_const_str_tolower; +extern const bcstring be_const_str_dot_len; +extern const bcstring be_const_str__request_from; +extern const bcstring be_const_str_has_arg; +extern const bcstring be_const_str_pow; +extern const bcstring be_const_str_push; +extern const bcstring be_const_str_read24; +extern const bcstring be_const_str_enabled; +extern const bcstring be_const_str_webclient; +extern const bcstring be_const_str_opt_neq; +extern const bcstring be_const_str_dot_p2; +extern const bcstring be_const_str_Wire; +extern const bcstring be_const_str_decrypt; +extern const bcstring be_const_str_floor; extern const bcstring be_const_str_issubclass; -extern const bcstring be_const_str_write_file; -extern const bcstring be_const_str_class; +extern const bcstring be_const_str_classname; +extern const bcstring be_const_str_rtc; +extern const bcstring be_const_str_add_driver; diff --git a/lib/libesp32/Berry/generate/be_const_strtab_def.h b/lib/libesp32/Berry/generate/be_const_strtab_def.h index 792cbd7f6..f031878a3 100644 --- a/lib/libesp32/Berry/generate/be_const_strtab_def.h +++ b/lib/libesp32/Berry/generate/be_const_strtab_def.h @@ -1,512 +1,517 @@ -be_define_const_str(SERIAL_5N1, "SERIAL_5N1", 3313031680u, 0, 10, NULL); -be_define_const_str(_global_addr, "_global_addr", 533766721u, 0, 12, &be_const_str_setmember); be_define_const_str(setmember, "setmember", 1432909441u, 0, 9, NULL); -be_define_const_str(OneWire, "OneWire", 2298990722u, 0, 7, &be_const_str__get_cb); -be_define_const_str(_get_cb, "_get_cb", 1448849122u, 0, 7, &be_const_str_classof); -be_define_const_str(classof, "classof", 1796577762u, 0, 7, NULL); -be_define_const_str(SERIAL_8O2, "SERIAL_8O2", 272345123u, 0, 10, &be_const_str___upper__); -be_define_const_str(__upper__, "__upper__", 3612202883u, 0, 9, &be_const_str_gamma10); -be_define_const_str(gamma10, "gamma10", 3472052483u, 0, 7, NULL); -be_define_const_str(copy, "copy", 3848464964u, 0, 4, NULL); -be_define_const_str(tostring, "tostring", 2299708645u, 0, 8, NULL); -be_define_const_str(dot_p1, ".p1", 249175686u, 0, 3, &be_const_str_item); -be_define_const_str(item, "item", 2671260646u, 0, 4, NULL); -be_define_const_str(read8, "read8", 2802788167u, 0, 5, &be_const_str_setbits); -be_define_const_str(setbits, "setbits", 2762408167u, 0, 7, &be_const_str_upper); -be_define_const_str(upper, "upper", 176974407u, 0, 5, NULL); -be_define_const_str(rad, "rad", 1358899048u, 0, 3, &be_const_str_web_send); -be_define_const_str(web_send, "web_send", 2989941448u, 0, 8, NULL); -be_define_const_str(load, "load", 3859241449u, 0, 4, NULL); -be_define_const_str(opt_add, "+", 772578730u, 0, 1, &be_const_str_hex); -be_define_const_str(hex, "hex", 4273249610u, 0, 3, &be_const_str_read12); -be_define_const_str(read12, "read12", 4291076970u, 0, 6, &be_const_str_end); -be_define_const_str(end, "end", 1787721130u, 56, 3, NULL); -be_define_const_str(chars_in_string, "chars_in_string", 3148785132u, 0, 15, &be_const_str_write8); -be_define_const_str(write8, "write8", 3133991532u, 0, 6, &be_const_str_def); -be_define_const_str(def, "def", 3310976652u, 55, 3, NULL); -be_define_const_str(select, "select", 297952813u, 0, 6, &be_const_str_type); -be_define_const_str(type, "type", 1361572173u, 0, 4, NULL); -be_define_const_str(global, "global", 503252654u, 0, 6, &be_const_str_yield); -be_define_const_str(yield, "yield", 1821831854u, 0, 5, NULL); -be_define_const_str(opt_eq, "==", 2431966415u, 0, 2, NULL); -be_define_const_str(SERIAL_8E1, "SERIAL_8E1", 2371121616u, 0, 10, &be_const_str_rtc); -be_define_const_str(rtc, "rtc", 1070575216u, 0, 3, &be_const_str_else); -be_define_const_str(else, "else", 3183434736u, 52, 4, NULL); -be_define_const_str(get_power, "get_power", 3009799377u, 0, 9, NULL); -be_define_const_str(addr, "addr", 1087856498u, 0, 4, &be_const_str_allocated); -be_define_const_str(allocated, "allocated", 429986098u, 0, 9, &be_const_str_finish); -be_define_const_str(finish, "finish", 1494643858u, 0, 6, NULL); -be_define_const_str(dot_p, ".p", 1171526419u, 0, 2, &be_const_str_getbits); -be_define_const_str(getbits, "getbits", 3094168979u, 0, 7, &be_const_str_tag); -be_define_const_str(tag, "tag", 2516003219u, 0, 3, NULL); -be_define_const_str(add, "add", 993596020u, 0, 3, &be_const_str_pin); -be_define_const_str(pin, "pin", 1866532500u, 0, 3, &be_const_str_set_timeouts); -be_define_const_str(set_timeouts, "set_timeouts", 3732850900u, 0, 12, &be_const_str_import); -be_define_const_str(import, "import", 288002260u, 66, 6, NULL); -be_define_const_str(SERIAL_6N1, "SERIAL_6N1", 198895701u, 0, 10, NULL); -be_define_const_str(SERIAL_8O1, "SERIAL_8O1", 289122742u, 0, 10, &be_const_str__settings_ptr); -be_define_const_str(_settings_ptr, "_settings_ptr", 1825772182u, 0, 13, &be_const_str_remove_cmd); -be_define_const_str(remove_cmd, "remove_cmd", 3832315702u, 0, 10, NULL); -be_define_const_str(__iterator__, "__iterator__", 3884039703u, 0, 12, &be_const_str_atan2); -be_define_const_str(atan2, "atan2", 3173440503u, 0, 5, &be_const_str_ctypes_bytes); -be_define_const_str(ctypes_bytes, "ctypes_bytes", 3879019703u, 0, 12, &be_const_str_millis); -be_define_const_str(millis, "millis", 1214679063u, 0, 6, NULL); -be_define_const_str(available, "available", 1727918744u, 0, 9, &be_const_str_delay); -be_define_const_str(delay, "delay", 1322381784u, 0, 5, &be_const_str_imin); -be_define_const_str(imin, "imin", 2714127864u, 0, 4, &be_const_str_shared_key); -be_define_const_str(shared_key, "shared_key", 2200833624u, 0, 10, &be_const_str_wire); -be_define_const_str(wire, "wire", 4082753944u, 0, 4, NULL); -be_define_const_str(_drivers, "_drivers", 3260328985u, 0, 8, &be_const_str_last_modified); -be_define_const_str(last_modified, "last_modified", 772177145u, 0, 13, &be_const_str_serial); -be_define_const_str(serial, "serial", 3687697785u, 0, 6, NULL); -be_define_const_str(opt_call, "()", 685372826u, 0, 2, &be_const_str_webclient); -be_define_const_str(webclient, "webclient", 4076389146u, 0, 9, NULL); -be_define_const_str(SERIAL_6E2, "SERIAL_6E2", 317471867u, 0, 10, &be_const_str_ctypes_bytes_dyn); -be_define_const_str(ctypes_bytes_dyn, "ctypes_bytes_dyn", 915205307u, 0, 16, &be_const_str_time_dump); -be_define_const_str(time_dump, "time_dump", 3330410747u, 0, 9, &be_const_str_static); -be_define_const_str(static, "static", 3532702267u, 71, 6, NULL); -be_define_const_str(classname, "classname", 1998589948u, 0, 9, &be_const_str_isrunning); -be_define_const_str(isrunning, "isrunning", 1688182268u, 0, 9, &be_const_str_top); +be_define_const_str(hex, "hex", 4273249610u, 0, 3, NULL); +be_define_const_str(arch, "arch", 2952804297u, 0, 4, &be_const_str_resolvecmnd); +be_define_const_str(resolvecmnd, "resolvecmnd", 993361485u, 0, 11, &be_const_str_resp_cmnd_done); +be_define_const_str(resp_cmnd_done, "resp_cmnd_done", 2601874875u, 0, 14, NULL); be_define_const_str(top, "top", 2802900028u, 0, 3, NULL); -be_define_const_str(remove, "remove", 3683784189u, 0, 6, NULL); -be_define_const_str(begin, "begin", 1748273790u, 0, 5, NULL); -be_define_const_str(content_stop, "content_stop", 658554751u, 0, 12, &be_const_str_deg); -be_define_const_str(deg, "deg", 3327754271u, 0, 3, &be_const_str_gc); -be_define_const_str(gc, "gc", 1042313471u, 0, 2, &be_const_str_gen_cb); -be_define_const_str(gen_cb, "gen_cb", 3245227551u, 0, 6, NULL); -be_define_const_str(reset, "reset", 1695364032u, 0, 5, NULL); -be_define_const_str(clear, "clear", 1550717474u, 0, 5, &be_const_str_skip); -be_define_const_str(skip, "skip", 1097563074u, 0, 4, NULL); -be_define_const_str(SERIAL_5E1, "SERIAL_5E1", 1163775235u, 0, 10, &be_const_str_has); -be_define_const_str(has, "has", 3988721635u, 0, 3, &be_const_str_raise); -be_define_const_str(raise, "raise", 1593437475u, 70, 5, NULL); -be_define_const_str(setitem, "setitem", 1554834596u, 0, 7, &be_const_str_write_bit); -be_define_const_str(write_bit, "write_bit", 2660990436u, 0, 9, NULL); -be_define_const_str(stop, "stop", 3411225317u, 0, 4, NULL); -be_define_const_str(AES_GCM, "AES_GCM", 3832208678u, 0, 7, NULL); -be_define_const_str(exec_cmd, "exec_cmd", 493567399u, 0, 8, &be_const_str_iter); -be_define_const_str(iter, "iter", 3124256359u, 0, 4, NULL); -be_define_const_str(ceil, "ceil", 1659167240u, 0, 4, &be_const_str_exp); -be_define_const_str(exp, "exp", 1923516200u, 0, 3, &be_const_str_tob64); -be_define_const_str(tob64, "tob64", 373777640u, 0, 5, &be_const_str_wire_scan); -be_define_const_str(wire_scan, "wire_scan", 2671275880u, 0, 9, NULL); -be_define_const_str(call, "call", 3018949801u, 0, 4, NULL); -be_define_const_str(cmd_res, "cmd_res", 921166762u, 0, 7, NULL); -be_define_const_str(opt_connect, "..", 2748622605u, 0, 2, &be_const_str_resolvecmnd); -be_define_const_str(resolvecmnd, "resolvecmnd", 993361485u, 0, 11, NULL); -be_define_const_str(SERIAL_6E1, "SERIAL_6E1", 334249486u, 0, 10, &be_const_str_try); -be_define_const_str(try, "try", 2887626766u, 68, 3, NULL); -be_define_const_str(_cb, "_cb", 4043300367u, 0, 3, NULL); -be_define_const_str(AudioOutput, "AudioOutput", 3257792048u, 0, 11, &be_const_str_check_privileged_access); -be_define_const_str(check_privileged_access, "check_privileged_access", 3692933968u, 0, 23, NULL); -be_define_const_str(SERIAL_6O2, "SERIAL_6O2", 316486129u, 0, 10, &be_const_str_content_send); -be_define_const_str(content_send, "content_send", 1673733649u, 0, 12, &be_const_str_tolower); -be_define_const_str(tolower, "tolower", 1042520049u, 0, 7, NULL); -be_define_const_str(detect, "detect", 8884370u, 0, 6, &be_const_str_imax); -be_define_const_str(imax, "imax", 3084515410u, 0, 4, &be_const_str_set_auth); -be_define_const_str(set_auth, "set_auth", 1057170930u, 0, 8, NULL); -be_define_const_str(depower, "depower", 3563819571u, 0, 7, &be_const_str_read24); -be_define_const_str(read24, "read24", 1808533811u, 0, 6, NULL); -be_define_const_str(add_header, "add_header", 927130612u, 0, 10, &be_const_str_kv); -be_define_const_str(kv, "kv", 1497177492u, 0, 2, &be_const_str_pin_used); -be_define_const_str(pin_used, "pin_used", 4033854612u, 0, 8, &be_const_str_publish_result); -be_define_const_str(publish_result, "publish_result", 2013351252u, 0, 14, &be_const_str_do); -be_define_const_str(do, "do", 1646057492u, 65, 2, NULL); -be_define_const_str(pow, "pow", 1479764693u, 0, 3, &be_const_str_read_bytes); -be_define_const_str(read_bytes, "read_bytes", 3576733173u, 0, 10, NULL); -be_define_const_str(SERIAL_5E2, "SERIAL_5E2", 1180552854u, 0, 10, &be_const_str_scale_uint); -be_define_const_str(scale_uint, "scale_uint", 3090811094u, 0, 10, NULL); -be_define_const_str(get, "get", 1410115415u, 0, 3, &be_const_str_remove_timer); -be_define_const_str(remove_timer, "remove_timer", 4141472215u, 0, 12, NULL); -be_define_const_str(dot_len, ".len", 850842136u, 0, 4, &be_const_str_Wire); -be_define_const_str(Wire, "Wire", 1938276536u, 0, 4, &be_const_str__begin_transmission); -be_define_const_str(_begin_transmission, "_begin_transmission", 2779461176u, 0, 19, &be_const_str_toupper); -be_define_const_str(toupper, "toupper", 3691983576u, 0, 7, NULL); -be_define_const_str(SERIAL_5N2, "SERIAL_5N2", 3363364537u, 0, 10, &be_const_str_arg_size); -be_define_const_str(arg_size, "arg_size", 3310243257u, 0, 8, NULL); -be_define_const_str(AudioFileSource, "AudioFileSource", 2959980058u, 0, 15, &be_const_str_I2C_Driver); -be_define_const_str(I2C_Driver, "I2C_Driver", 1714501658u, 0, 10, &be_const_str_decrypt); -be_define_const_str(decrypt, "decrypt", 2886974618u, 0, 7, NULL); -be_define_const_str(digital_write, "digital_write", 3435877979u, 0, 13, &be_const_str_input); -be_define_const_str(input, "input", 4191711099u, 0, 5, NULL); -be_define_const_str(char, "char", 2823553821u, 0, 4, &be_const_str_floor); -be_define_const_str(floor, "floor", 3102149661u, 0, 5, &be_const_str_real); +be_define_const_str(content_start, "content_start", 2937509069u, 0, 13, &be_const_str_deg); +be_define_const_str(deg, "deg", 3327754271u, 0, 3, &be_const_str_fromptr); +be_define_const_str(fromptr, "fromptr", 666189689u, 0, 7, &be_const_str_time_dump); +be_define_const_str(time_dump, "time_dump", 3330410747u, 0, 9, NULL); +be_define_const_str(compile, "compile", 1000265118u, 0, 7, &be_const_str_members); +be_define_const_str(members, "members", 937576464u, 0, 7, NULL); +be_define_const_str(arg_name, "arg_name", 1345046155u, 0, 8, &be_const_str_real); be_define_const_str(real, "real", 3604983901u, 0, 4, NULL); -be_define_const_str(AudioGenerator, "AudioGenerator", 1839297342u, 0, 14, &be_const_str__cmd); -be_define_const_str(_cmd, "_cmd", 3419822142u, 0, 4, &be_const_str_enabled); -be_define_const_str(enabled, "enabled", 49525662u, 0, 7, &be_const_str_int); -be_define_const_str(int, "int", 2515107422u, 0, 3, NULL); -be_define_const_str(byte, "byte", 1683620383u, 0, 4, &be_const_str_resp_cmnd_error); -be_define_const_str(resp_cmnd_error, "resp_cmnd_error", 2404088863u, 0, 15, NULL); -be_define_const_str(dot_size, ".size", 1965188224u, 0, 5, NULL); -be_define_const_str(list, "list", 217798785u, 0, 4, &be_const_str_reset_search); -be_define_const_str(reset_search, "reset_search", 1350414305u, 0, 12, NULL); -be_define_const_str(SERIAL_7N2, "SERIAL_7N2", 1874282627u, 0, 10, &be_const_str_set); -be_define_const_str(set, "set", 3324446467u, 0, 3, &be_const_str_elif); -be_define_const_str(elif, "elif", 3232090307u, 51, 4, NULL); -be_define_const_str(Tasmota, "Tasmota", 4047617668u, 0, 7, &be_const_str_get_switch); -be_define_const_str(get_switch, "get_switch", 164821028u, 0, 10, NULL); -be_define_const_str(read, "read", 3470762949u, 0, 4, NULL); -be_define_const_str(__lower__, "__lower__", 123855590u, 0, 9, &be_const_str__read); -be_define_const_str(_read, "_read", 346717030u, 0, 5, &be_const_str_asin); +be_define_const_str(insert, "insert", 3332609576u, 0, 6, NULL); +be_define_const_str(open, "open", 3546203337u, 0, 4, NULL); +be_define_const_str(ctypes_bytes, "ctypes_bytes", 3879019703u, 0, 12, &be_const_str_tag); +be_define_const_str(tag, "tag", 2516003219u, 0, 3, NULL); +be_define_const_str(reset, "reset", 1695364032u, 0, 5, &be_const_str_toupper); +be_define_const_str(toupper, "toupper", 3691983576u, 0, 7, NULL); +be_define_const_str(POST, "POST", 1929554311u, 0, 4, &be_const_str_SERIAL_6O2); +be_define_const_str(SERIAL_6O2, "SERIAL_6O2", 316486129u, 0, 10, &be_const_str_iter); +be_define_const_str(iter, "iter", 3124256359u, 0, 4, &be_const_str_load); +be_define_const_str(load, "load", 3859241449u, 0, 4, NULL); +be_define_const_str(available, "available", 1727918744u, 0, 9, &be_const_str_ceil); +be_define_const_str(ceil, "ceil", 1659167240u, 0, 4, &be_const_str_clear); +be_define_const_str(clear, "clear", 1550717474u, 0, 5, &be_const_str_digital_read); +be_define_const_str(digital_read, "digital_read", 3585496928u, 0, 12, NULL); +be_define_const_str(_get_cb, "_get_cb", 1448849122u, 0, 7, &be_const_str_bytes); +be_define_const_str(bytes, "bytes", 1706151940u, 0, 5, &be_const_str_settings); +be_define_const_str(settings, "settings", 1745255176u, 0, 8, NULL); +be_define_const_str(get_string, "get_string", 4195847969u, 0, 10, NULL); +be_define_const_str(asstring, "asstring", 1298225088u, 0, 8, &be_const_str_pin_used); +be_define_const_str(pin_used, "pin_used", 4033854612u, 0, 8, &be_const_str_pop); +be_define_const_str(pop, "pop", 1362321360u, 0, 3, NULL); +be_define_const_str(static, "static", 3532702267u, 71, 6, NULL); +be_define_const_str(AES_GCM, "AES_GCM", 3832208678u, 0, 7, &be_const_str_SERIAL_8N2); +be_define_const_str(SERIAL_8N2, "SERIAL_8N2", 2386074854u, 0, 10, NULL); +be_define_const_str(close, "close", 667630371u, 0, 5, &be_const_str_set_power); +be_define_const_str(set_power, "set_power", 549820893u, 0, 9, NULL); +be_define_const_str(find_op, "find_op", 3766713376u, 0, 7, NULL); +be_define_const_str(get, "get", 1410115415u, 0, 3, NULL); +be_define_const_str(print, "print", 372738696u, 0, 5, &be_const_str_publish_result); +be_define_const_str(publish_result, "publish_result", 2013351252u, 0, 14, NULL); +be_define_const_str(target_search, "target_search", 1947846553u, 0, 13, NULL); +be_define_const_str(_ccmd, "_ccmd", 2163421413u, 0, 5, &be_const_str_fromb64); +be_define_const_str(fromb64, "fromb64", 2717019639u, 0, 7, &be_const_str_module); +be_define_const_str(module, "module", 3617558685u, 0, 6, NULL); +be_define_const_str(allocated, "allocated", 429986098u, 0, 9, NULL); +be_define_const_str(GET, "GET", 2531704439u, 0, 3, NULL); +be_define_const_str(SERIAL_8E1, "SERIAL_8E1", 2371121616u, 0, 10, &be_const_str_classof); +be_define_const_str(classof, "classof", 1796577762u, 0, 7, &be_const_str_cos); +be_define_const_str(cos, "cos", 4220379804u, 0, 3, NULL); +be_define_const_str(assert, "assert", 2774883451u, 0, 6, &be_const_str_content_send); +be_define_const_str(content_send, "content_send", 1673733649u, 0, 12, &be_const_str_read13); +be_define_const_str(read13, "read13", 12887293u, 0, 6, &be_const_str_reverse); +be_define_const_str(reverse, "reverse", 558918661u, 0, 7, &be_const_str_set_timer); +be_define_const_str(set_timer, "set_timer", 2135414533u, 0, 9, &be_const_str_class); +be_define_const_str(class, "class", 2872970239u, 57, 5, NULL); +be_define_const_str(codedump, "codedump", 1786337906u, 0, 8, &be_const_str_isrunning); +be_define_const_str(isrunning, "isrunning", 1688182268u, 0, 9, &be_const_str_publish); +be_define_const_str(publish, "publish", 264247304u, 0, 7, &be_const_str_range); +be_define_const_str(range, "range", 4208725202u, 0, 5, &be_const_str_write); +be_define_const_str(write, "write", 3190202204u, 0, 5, NULL); +be_define_const_str(opt_connect, "..", 2748622605u, 0, 2, &be_const_str_SERIAL_7O1); +be_define_const_str(SERIAL_7O1, "SERIAL_7O1", 1823802675u, 0, 10, NULL); +be_define_const_str(update, "update", 672109684u, 0, 6, NULL); +be_define_const_str(_cmd, "_cmd", 3419822142u, 0, 4, &be_const_str_isnan); +be_define_const_str(isnan, "isnan", 2981347434u, 0, 5, &be_const_str_resp_cmnd_failed); +be_define_const_str(resp_cmnd_failed, "resp_cmnd_failed", 2136281562u, 0, 16, NULL); +be_define_const_str(SERIAL_5O1, "SERIAL_5O1", 3782657917u, 0, 10, &be_const_str_abs); +be_define_const_str(abs, "abs", 709362235u, 0, 3, NULL); +be_define_const_str(SERIAL_7E2, "SERIAL_7E2", 97385204u, 0, 10, NULL); +be_define_const_str(SERIAL_6N1, "SERIAL_6N1", 198895701u, 0, 10, &be_const_str__cb); +be_define_const_str(_cb, "_cb", 4043300367u, 0, 3, &be_const_str_depower); +be_define_const_str(depower, "depower", 3563819571u, 0, 7, NULL); +be_define_const_str(Tasmota, "Tasmota", 4047617668u, 0, 7, &be_const_str_item); +be_define_const_str(item, "item", 2671260646u, 0, 4, &be_const_str_set_useragent); +be_define_const_str(set_useragent, "set_useragent", 612237244u, 0, 13, &be_const_str_wire2); +be_define_const_str(wire2, "wire2", 3229499038u, 0, 5, NULL); +be_define_const_str(time_reached, "time_reached", 2075136773u, 0, 12, NULL); +be_define_const_str(chars_in_string, "chars_in_string", 3148785132u, 0, 15, &be_const_str_false); +be_define_const_str(false, "false", 184981848u, 62, 5, NULL); +be_define_const_str(add_rule, "add_rule", 596540743u, 0, 8, &be_const_str_setbits); +be_define_const_str(setbits, "setbits", 2762408167u, 0, 7, &be_const_str_write_file); +be_define_const_str(write_file, "write_file", 3177658879u, 0, 10, NULL); +be_define_const_str(SERIAL_8O1, "SERIAL_8O1", 289122742u, 0, 10, &be_const_str_wd); +be_define_const_str(wd, "wd", 1531424278u, 0, 2, &be_const_str_wire_scan); +be_define_const_str(wire_scan, "wire_scan", 2671275880u, 0, 9, NULL); +be_define_const_str(AudioFileSourceFS, "AudioFileSourceFS", 1839147653u, 0, 17, &be_const_str_get_free_heap); +be_define_const_str(get_free_heap, "get_free_heap", 625069757u, 0, 13, NULL); +be_define_const_str(AudioGenerator, "AudioGenerator", 1839297342u, 0, 14, &be_const_str_SERIAL_5E2); +be_define_const_str(SERIAL_5E2, "SERIAL_5E2", 1180552854u, 0, 10, NULL); +be_define_const_str(_global_addr, "_global_addr", 533766721u, 0, 12, &be_const_str_content_send_style); +be_define_const_str(content_send_style, "content_send_style", 1087907647u, 0, 18, &be_const_str_remove_timer); +be_define_const_str(remove_timer, "remove_timer", 4141472215u, 0, 12, &be_const_str_tr); +be_define_const_str(tr, "tr", 1195724803u, 0, 2, NULL); +be_define_const_str(dot_w, ".w", 1255414514u, 0, 2, NULL); +be_define_const_str(MD5, "MD5", 1935726387u, 0, 3, NULL); +be_define_const_str(break, "break", 3378807160u, 58, 5, NULL); +be_define_const_str(digital_write, "digital_write", 3435877979u, 0, 13, NULL); be_define_const_str(asin, "asin", 4272848550u, 0, 4, NULL); -be_define_const_str(POST, "POST", 1929554311u, 0, 4, &be_const_str_arg); -be_define_const_str(arg, "arg", 1047474471u, 0, 3, &be_const_str_reduce); -be_define_const_str(reduce, "reduce", 2002030311u, 0, 6, NULL); -be_define_const_str(deinit, "deinit", 2345559592u, 0, 6, &be_const_str_save); -be_define_const_str(save, "save", 3439296072u, 0, 4, NULL); -be_define_const_str(SERIAL_8E2, "SERIAL_8E2", 2421454473u, 0, 10, &be_const_str_get_size); -be_define_const_str(get_size, "get_size", 2803644713u, 0, 8, &be_const_str_search); -be_define_const_str(search, "search", 2150836393u, 0, 6, &be_const_str_srand); -be_define_const_str(srand, "srand", 465518633u, 0, 5, NULL); -be_define_const_str(isnan, "isnan", 2981347434u, 0, 5, NULL); -be_define_const_str(arg_name, "arg_name", 1345046155u, 0, 8, &be_const_str_content_flush); -be_define_const_str(content_flush, "content_flush", 214922475u, 0, 13, NULL); -be_define_const_str(get_light, "get_light", 381930476u, 0, 9, NULL); +be_define_const_str(_def, "_def", 1985022181u, 0, 4, &be_const_str_exec_cmd); +be_define_const_str(exec_cmd, "exec_cmd", 493567399u, 0, 8, &be_const_str_exists); +be_define_const_str(exists, "exists", 1002329533u, 0, 6, &be_const_str_flush); +be_define_const_str(flush, "flush", 3002334877u, 0, 5, &be_const_str_as); +be_define_const_str(as, "as", 1579491469u, 67, 2, NULL); +be_define_const_str(set_light, "set_light", 3176076152u, 0, 9, &be_const_str_time_str); +be_define_const_str(time_str, "time_str", 2613827612u, 0, 8, NULL); +be_define_const_str(arg_size, "arg_size", 3310243257u, 0, 8, &be_const_str_bus); +be_define_const_str(bus, "bus", 1607822841u, 0, 3, NULL); +be_define_const_str(opt_eq, "==", 2431966415u, 0, 2, &be_const_str_try_rule); +be_define_const_str(try_rule, "try_rule", 1986449405u, 0, 8, NULL); +be_define_const_str(kv, "kv", 1497177492u, 0, 2, &be_const_str_reverse_gamma10); +be_define_const_str(reverse_gamma10, "reverse_gamma10", 739112262u, 0, 15, NULL); +be_define_const_str(tostring, "tostring", 2299708645u, 0, 8, NULL); +be_define_const_str(format, "format", 3114108242u, 0, 6, &be_const_str_tob64); +be_define_const_str(tob64, "tob64", 373777640u, 0, 5, &be_const_str_continue); +be_define_const_str(continue, "continue", 2977070660u, 59, 8, NULL); +be_define_const_str(log, "log", 1062293841u, 0, 3, NULL); +be_define_const_str(SERIAL_7N1, "SERIAL_7N1", 1891060246u, 0, 10, &be_const_str_lower); +be_define_const_str(lower, "lower", 3038577850u, 0, 5, NULL); +be_define_const_str(stop, "stop", 3411225317u, 0, 4, NULL); +be_define_const_str(count, "count", 967958004u, 0, 5, &be_const_str_encrypt); +be_define_const_str(encrypt, "encrypt", 2194327650u, 0, 7, &be_const_str_resp_cmnd_str); +be_define_const_str(resp_cmnd_str, "resp_cmnd_str", 737845590u, 0, 13, NULL); +be_define_const_str(byte, "byte", 1683620383u, 0, 4, NULL); +be_define_const_str(fromstring, "fromstring", 610302344u, 0, 10, &be_const_str_run_deferred); +be_define_const_str(run_deferred, "run_deferred", 371594696u, 0, 12, &be_const_str_setitem); +be_define_const_str(setitem, "setitem", 1554834596u, 0, 7, NULL); +be_define_const_str(cmd, "cmd", 4136785899u, 0, 3, &be_const_str_event); +be_define_const_str(event, "event", 4264611999u, 0, 5, NULL); +be_define_const_str(SERIAL_6E1, "SERIAL_6E1", 334249486u, 0, 10, &be_const_str_SERIAL_6O1); +be_define_const_str(SERIAL_6O1, "SERIAL_6O1", 266153272u, 0, 10, &be_const_str_remove_driver); +be_define_const_str(remove_driver, "remove_driver", 1030243768u, 0, 13, NULL); +be_define_const_str(EC_C25519, "EC_C25519", 95492591u, 0, 9, NULL); +be_define_const_str(read12, "read12", 4291076970u, 0, 6, NULL); +be_define_const_str(_write, "_write", 2215462825u, 0, 6, NULL); +be_define_const_str(opt_call, "()", 685372826u, 0, 2, &be_const_str_AudioOutput); +be_define_const_str(AudioOutput, "AudioOutput", 3257792048u, 0, 11, &be_const_str_attrdump); +be_define_const_str(attrdump, "attrdump", 1521571304u, 0, 8, &be_const_str_int); +be_define_const_str(int, "int", 2515107422u, 0, 3, NULL); +be_define_const_str(AudioGeneratorMP3, "AudioGeneratorMP3", 2199818488u, 0, 17, &be_const_str_add_header); +be_define_const_str(add_header, "add_header", 927130612u, 0, 10, NULL); +be_define_const_str(ctypes_bytes_dyn, "ctypes_bytes_dyn", 915205307u, 0, 16, &be_const_str_keys); +be_define_const_str(keys, "keys", 4182378701u, 0, 4, NULL); +be_define_const_str(set_auth, "set_auth", 1057170930u, 0, 8, &be_const_str_def); +be_define_const_str(def, "def", 3310976652u, 55, 3, NULL); +be_define_const_str(, "", 2166136261u, 0, 0, &be_const_str_SERIAL_5N2); +be_define_const_str(SERIAL_5N2, "SERIAL_5N2", 3363364537u, 0, 10, &be_const_str__rules); +be_define_const_str(_rules, "_rules", 4266217105u, 0, 6, &be_const_str_has); +be_define_const_str(has, "has", 3988721635u, 0, 3, &be_const_str_set); +be_define_const_str(set, "set", 3324446467u, 0, 3, NULL); +be_define_const_str(public_key, "public_key", 4169142980u, 0, 10, NULL); +be_define_const_str(get_power, "get_power", 3009799377u, 0, 9, &be_const_str_type); +be_define_const_str(type, "type", 1361572173u, 0, 4, NULL); +be_define_const_str(opt_add, "+", 772578730u, 0, 1, &be_const_str_dot_size); +be_define_const_str(dot_size, ".size", 1965188224u, 0, 5, &be_const_str_set_timeouts); +be_define_const_str(set_timeouts, "set_timeouts", 3732850900u, 0, 12, &be_const_str_tomap); +be_define_const_str(tomap, "tomap", 612167626u, 0, 5, NULL); +be_define_const_str(getbits, "getbits", 3094168979u, 0, 7, &be_const_str_sinh); +be_define_const_str(sinh, "sinh", 282220607u, 0, 4, &be_const_str_sqrt); be_define_const_str(sqrt, "sqrt", 2112764879u, 0, 4, NULL); -be_define_const_str(_end_transmission, "_end_transmission", 3237480400u, 0, 17, &be_const_str_listdir); -be_define_const_str(listdir, "listdir", 2005220720u, 0, 7, &be_const_str_log10); -be_define_const_str(log10, "log10", 2346846000u, 0, 5, &be_const_str_pop); -be_define_const_str(pop, "pop", 1362321360u, 0, 3, &be_const_str_read32); -be_define_const_str(read32, "read32", 1741276240u, 0, 6, &be_const_str_for); +be_define_const_str(dot_p1, ".p1", 249175686u, 0, 3, &be_const_str_begin); +be_define_const_str(begin, "begin", 1748273790u, 0, 5, &be_const_str_delay); +be_define_const_str(delay, "delay", 1322381784u, 0, 5, &be_const_str_scan); +be_define_const_str(scan, "scan", 3974641896u, 0, 4, &be_const_str_for); be_define_const_str(for, "for", 2901640080u, 54, 3, NULL); -be_define_const_str(exec_tele, "exec_tele", 1020751601u, 0, 9, &be_const_str_log); -be_define_const_str(log, "log", 1062293841u, 0, 3, &be_const_str_map); +be_define_const_str(read8, "read8", 2802788167u, 0, 5, NULL); +be_define_const_str(AudioGeneratorWAV, "AudioGeneratorWAV", 2746509368u, 0, 17, &be_const_str_get_light); +be_define_const_str(get_light, "get_light", 381930476u, 0, 9, NULL); +be_define_const_str(_global_def, "_global_def", 646007001u, 0, 11, &be_const_str_map); be_define_const_str(map, "map", 3751997361u, 0, 3, &be_const_str_redirect); be_define_const_str(redirect, "redirect", 389758641u, 0, 8, NULL); -be_define_const_str(format, "format", 3114108242u, 0, 6, &be_const_str_pi); -be_define_const_str(pi, "pi", 1213090802u, 0, 2, &be_const_str_range); -be_define_const_str(range, "range", 4208725202u, 0, 5, NULL); -be_define_const_str(SERIAL_7E2, "SERIAL_7E2", 97385204u, 0, 10, &be_const_str_count); -be_define_const_str(count, "count", 967958004u, 0, 5, &be_const_str_update); -be_define_const_str(update, "update", 672109684u, 0, 6, NULL); -be_define_const_str(SERIAL_7N1, "SERIAL_7N1", 1891060246u, 0, 10, &be_const_str_find_key_i); -be_define_const_str(find_key_i, "find_key_i", 850136726u, 0, 10, NULL); -be_define_const_str(content_button, "content_button", 1956476087u, 0, 14, NULL); -be_define_const_str(AudioGeneratorMP3, "AudioGeneratorMP3", 2199818488u, 0, 17, &be_const_str_AudioGeneratorWAV); -be_define_const_str(AudioGeneratorWAV, "AudioGeneratorWAV", 2746509368u, 0, 17, &be_const_str__buffer); -be_define_const_str(_buffer, "_buffer", 2044888568u, 0, 7, &be_const_str_remove_driver); -be_define_const_str(remove_driver, "remove_driver", 1030243768u, 0, 13, &be_const_str_false); -be_define_const_str(false, "false", 184981848u, 62, 5, NULL); -be_define_const_str(fromptr, "fromptr", 666189689u, 0, 7, NULL); -be_define_const_str(geti, "geti", 2381006490u, 0, 4, &be_const_str_lower); -be_define_const_str(lower, "lower", 3038577850u, 0, 5, &be_const_str_nan); -be_define_const_str(nan, "nan", 797905850u, 0, 3, NULL); -be_define_const_str(assert, "assert", 2774883451u, 0, 6, NULL); -be_define_const_str(time_str, "time_str", 2613827612u, 0, 8, NULL); -be_define_const_str(exists, "exists", 1002329533u, 0, 6, &be_const_str_read13); -be_define_const_str(read13, "read13", 12887293u, 0, 6, &be_const_str_set_power); -be_define_const_str(set_power, "set_power", 549820893u, 0, 9, NULL); -be_define_const_str(seti, "seti", 1500556254u, 0, 4, &be_const_str_toptr); -be_define_const_str(toptr, "toptr", 3379847454u, 0, 5, NULL); -be_define_const_str(acos, "acos", 1006755615u, 0, 4, NULL); -be_define_const_str(find_op, "find_op", 3766713376u, 0, 7, NULL); +be_define_const_str(_ptr, "_ptr", 306235816u, 0, 4, &be_const_str_isinstance); be_define_const_str(isinstance, "isinstance", 3669352738u, 0, 10, NULL); -be_define_const_str(cb_dispatch, "cb_dispatch", 1741510499u, 0, 11, NULL); -be_define_const_str(SERIAL_5O2, "SERIAL_5O2", 3732325060u, 0, 10, &be_const_str_bytes); -be_define_const_str(bytes, "bytes", 1706151940u, 0, 5, &be_const_str_public_key); -be_define_const_str(public_key, "public_key", 4169142980u, 0, 10, &be_const_str_continue); -be_define_const_str(continue, "continue", 2977070660u, 59, 8, NULL); -be_define_const_str(, "", 2166136261u, 0, 0, &be_const_str__available); -be_define_const_str(_available, "_available", 1306196581u, 0, 10, &be_const_str__def); -be_define_const_str(_def, "_def", 1985022181u, 0, 4, &be_const_str_i2c_enabled); -be_define_const_str(i2c_enabled, "i2c_enabled", 218388101u, 0, 11, &be_const_str_reverse); -be_define_const_str(reverse, "reverse", 558918661u, 0, 7, &be_const_str_true); -be_define_const_str(true, "true", 1303515621u, 61, 4, NULL); -be_define_const_str(dac_voltage, "dac_voltage", 1552257222u, 0, 11, &be_const_str_name); -be_define_const_str(name, "name", 2369371622u, 0, 4, &be_const_str_reverse_gamma10); -be_define_const_str(reverse_gamma10, "reverse_gamma10", 739112262u, 0, 15, NULL); -be_define_const_str(add_rule, "add_rule", 596540743u, 0, 8, &be_const_str_dump); -be_define_const_str(dump, "dump", 3663001223u, 0, 4, NULL); -be_define_const_str(AudioOutputI2S, "AudioOutputI2S", 638031784u, 0, 14, &be_const_str_attrdump); -be_define_const_str(attrdump, "attrdump", 1521571304u, 0, 8, &be_const_str_fromstring); -be_define_const_str(fromstring, "fromstring", 610302344u, 0, 10, &be_const_str_publish); -be_define_const_str(publish, "publish", 264247304u, 0, 7, &be_const_str_wifi); -be_define_const_str(wifi, "wifi", 120087624u, 0, 4, NULL); -be_define_const_str(_write, "_write", 2215462825u, 0, 6, NULL); -be_define_const_str(resp_cmnd, "resp_cmnd", 2869459626u, 0, 9, &be_const_str_tomap); -be_define_const_str(tomap, "tomap", 612167626u, 0, 5, NULL); -be_define_const_str(content_start, "content_start", 2937509069u, 0, 13, &be_const_str_traceback); -be_define_const_str(traceback, "traceback", 3385188109u, 0, 9, &be_const_str_as); -be_define_const_str(as, "as", 1579491469u, 67, 2, NULL); -be_define_const_str(memory, "memory", 2229924270u, 0, 6, &be_const_str_pin_mode); -be_define_const_str(pin_mode, "pin_mode", 3258314030u, 0, 8, NULL); -be_define_const_str(EC_C25519, "EC_C25519", 95492591u, 0, 9, NULL); -be_define_const_str(str, "str", 3259748752u, 0, 3, &be_const_str_tanh); -be_define_const_str(tanh, "tanh", 153638352u, 0, 4, &be_const_str_write_bytes); -be_define_const_str(write_bytes, "write_bytes", 1227543792u, 0, 11, &be_const_str_except); -be_define_const_str(except, "except", 950914032u, 69, 6, NULL); -be_define_const_str(get_option, "get_option", 2123730033u, 0, 10, NULL); -be_define_const_str(dot_w, ".w", 1255414514u, 0, 2, NULL); -be_define_const_str(SERIAL_7O1, "SERIAL_7O1", 1823802675u, 0, 10, &be_const_str_SERIAL_8N1); -be_define_const_str(SERIAL_8N1, "SERIAL_8N1", 2369297235u, 0, 10, &be_const_str_init); -be_define_const_str(init, "init", 380752755u, 0, 4, NULL); -be_define_const_str(_timers, "_timers", 2600100916u, 0, 7, &be_const_str_super); -be_define_const_str(super, "super", 4152230356u, 0, 5, NULL); -be_define_const_str(GET, "GET", 2531704439u, 0, 3, &be_const_str_fromb64); -be_define_const_str(fromb64, "fromb64", 2717019639u, 0, 7, NULL); -be_define_const_str(break, "break", 3378807160u, 58, 5, NULL); -be_define_const_str(_global_def, "_global_def", 646007001u, 0, 11, &be_const_str_bus); -be_define_const_str(bus, "bus", 1607822841u, 0, 3, NULL); -be_define_const_str(find, "find", 3186656602u, 0, 4, &be_const_str_resp_cmnd_failed); -be_define_const_str(resp_cmnd_failed, "resp_cmnd_failed", 2136281562u, 0, 16, NULL); -be_define_const_str(SERIAL_6N2, "SERIAL_6N2", 148562844u, 0, 10, &be_const_str__request_from); -be_define_const_str(_request_from, "_request_from", 3965148604u, 0, 13, &be_const_str_cos); -be_define_const_str(cos, "cos", 4220379804u, 0, 3, &be_const_str_cosh); -be_define_const_str(cosh, "cosh", 4099687964u, 0, 4, &be_const_str_set_useragent); -be_define_const_str(set_useragent, "set_useragent", 612237244u, 0, 13, &be_const_str_size); -be_define_const_str(size, "size", 597743964u, 0, 4, &be_const_str_web_send_decimal); -be_define_const_str(web_send_decimal, "web_send_decimal", 1407210204u, 0, 16, &be_const_str_write); -be_define_const_str(write, "write", 3190202204u, 0, 5, NULL); -be_define_const_str(module, "module", 3617558685u, 0, 6, &be_const_str_try_rule); -be_define_const_str(try_rule, "try_rule", 1986449405u, 0, 8, NULL); -be_define_const_str(var, "var", 2317739966u, 64, 3, NULL); -be_define_const_str(content_send_style, "content_send_style", 1087907647u, 0, 18, &be_const_str_sinh); -be_define_const_str(sinh, "sinh", 282220607u, 0, 4, &be_const_str_return); -be_define_const_str(return, "return", 2246981567u, 60, 6, NULL); -be_define_const_str(asstring, "asstring", 1298225088u, 0, 8, &be_const_str_digital_read); -be_define_const_str(digital_read, "digital_read", 3585496928u, 0, 12, &be_const_str_has_arg); -be_define_const_str(has_arg, "has_arg", 424878688u, 0, 7, &be_const_str_number); -be_define_const_str(number, "number", 467038368u, 0, 6, &be_const_str_remove_rule); -be_define_const_str(remove_rule, "remove_rule", 3456211328u, 0, 11, NULL); -be_define_const_str(get_string, "get_string", 4195847969u, 0, 10, &be_const_str_resize); -be_define_const_str(resize, "resize", 3514612129u, 0, 6, NULL); -be_define_const_str(encrypt, "encrypt", 2194327650u, 0, 7, NULL); -be_define_const_str(opt_neq, "!=", 2428715011u, 0, 2, &be_const_str_add_driver); -be_define_const_str(add_driver, "add_driver", 1654458371u, 0, 10, &be_const_str_close); -be_define_const_str(close, "close", 667630371u, 0, 5, &be_const_str_member); -be_define_const_str(member, "member", 719708611u, 0, 6, &be_const_str_response_append); -be_define_const_str(response_append, "response_append", 450346371u, 0, 15, &be_const_str_split); -be_define_const_str(split, "split", 2276994531u, 0, 5, &be_const_str_strftime); -be_define_const_str(strftime, "strftime", 187738851u, 0, 8, NULL); -be_define_const_str(exec_rules, "exec_rules", 1445221092u, 0, 10, NULL); -be_define_const_str(AudioFileSourceFS, "AudioFileSourceFS", 1839147653u, 0, 17, &be_const_str__ccmd); -be_define_const_str(_ccmd, "_ccmd", 2163421413u, 0, 5, &be_const_str_set_timer); -be_define_const_str(set_timer, "set_timer", 2135414533u, 0, 9, &be_const_str_time_reached); -be_define_const_str(time_reached, "time_reached", 2075136773u, 0, 12, NULL); -be_define_const_str(SERIAL_7O2, "SERIAL_7O2", 1840580294u, 0, 10, &be_const_str_SERIAL_8N2); -be_define_const_str(SERIAL_8N2, "SERIAL_8N2", 2386074854u, 0, 10, &be_const_str_if); -be_define_const_str(if, "if", 959999494u, 50, 2, NULL); -be_define_const_str(_ptr, "_ptr", 306235816u, 0, 4, &be_const_str_insert); -be_define_const_str(insert, "insert", 3332609576u, 0, 6, &be_const_str_print); -be_define_const_str(print, "print", 372738696u, 0, 5, &be_const_str_run_deferred); -be_define_const_str(run_deferred, "run_deferred", 371594696u, 0, 12, &be_const_str_scan); -be_define_const_str(scan, "scan", 3974641896u, 0, 4, &be_const_str_settings); -be_define_const_str(settings, "settings", 1745255176u, 0, 8, NULL); -be_define_const_str(arch, "arch", 2952804297u, 0, 4, &be_const_str_open); -be_define_const_str(open, "open", 3546203337u, 0, 4, NULL); -be_define_const_str(cmd, "cmd", 4136785899u, 0, 3, &be_const_str_loop); -be_define_const_str(loop, "loop", 3723446379u, 0, 4, &be_const_str_wire1); -be_define_const_str(wire1, "wire1", 3212721419u, 0, 5, NULL); -be_define_const_str(nil, "nil", 228849900u, 63, 3, NULL); -be_define_const_str(SERIAL_7E1, "SERIAL_7E1", 147718061u, 0, 10, &be_const_str_keys); -be_define_const_str(keys, "keys", 4182378701u, 0, 4, &be_const_str_sin); -be_define_const_str(sin, "sin", 3761252941u, 0, 3, NULL); -be_define_const_str(calldepth, "calldepth", 3122364302u, 0, 9, &be_const_str_while); -be_define_const_str(while, "while", 231090382u, 53, 5, NULL); -be_define_const_str(counters, "counters", 4095866864u, 0, 8, &be_const_str_members); -be_define_const_str(members, "members", 937576464u, 0, 7, &be_const_str_on); -be_define_const_str(on, "on", 1630810064u, 0, 2, NULL); -be_define_const_str(_rules, "_rules", 4266217105u, 0, 6, &be_const_str_collect); -be_define_const_str(collect, "collect", 2399039025u, 0, 7, &be_const_str_url_encode); -be_define_const_str(url_encode, "url_encode", 528392145u, 0, 10, NULL); -be_define_const_str(codedump, "codedump", 1786337906u, 0, 8, NULL); -be_define_const_str(dot_p2, ".p2", 232398067u, 0, 3, &be_const_str_MD5); -be_define_const_str(MD5, "MD5", 1935726387u, 0, 3, &be_const_str__settings_def); -be_define_const_str(_settings_def, "_settings_def", 3775560307u, 0, 13, NULL); -be_define_const_str(erase, "erase", 1010949589u, 0, 5, NULL); -be_define_const_str(gamma8, "gamma8", 3802843830u, 0, 6, &be_const_str_rand); -be_define_const_str(rand, "rand", 2711325910u, 0, 4, &be_const_str_resp_cmnd_str); -be_define_const_str(resp_cmnd_str, "resp_cmnd_str", 737845590u, 0, 13, &be_const_str_state); +be_define_const_str(pin, "pin", 1866532500u, 0, 3, &be_const_str_size); +be_define_const_str(size, "size", 597743964u, 0, 4, &be_const_str_state); be_define_const_str(state, "state", 2016490230u, 0, 5, NULL); -be_define_const_str(SERIAL_6O1, "SERIAL_6O1", 266153272u, 0, 10, &be_const_str_contains); -be_define_const_str(contains, "contains", 1825239352u, 0, 8, &be_const_str_set_light); -be_define_const_str(set_light, "set_light", 3176076152u, 0, 9, &be_const_str_setrange); -be_define_const_str(setrange, "setrange", 3794019032u, 0, 8, &be_const_str_tan); +be_define_const_str(dot_p, ".p", 1171526419u, 0, 2, &be_const_str__drivers); +be_define_const_str(_drivers, "_drivers", 3260328985u, 0, 8, &be_const_str_erase); +be_define_const_str(erase, "erase", 1010949589u, 0, 5, NULL); +be_define_const_str(I2C_Driver, "I2C_Driver", 1714501658u, 0, 10, &be_const_str_addr); +be_define_const_str(addr, "addr", 1087856498u, 0, 4, &be_const_str_copy); +be_define_const_str(copy, "copy", 3848464964u, 0, 4, &be_const_str_find_key_i); +be_define_const_str(find_key_i, "find_key_i", 850136726u, 0, 10, &be_const_str_pin_mode); +be_define_const_str(pin_mode, "pin_mode", 3258314030u, 0, 8, &be_const_str_setrange); +be_define_const_str(setrange, "setrange", 3794019032u, 0, 8, NULL); +be_define_const_str(SERIAL_8N1, "SERIAL_8N1", 2369297235u, 0, 10, &be_const_str_char); +be_define_const_str(char, "char", 2823553821u, 0, 4, &be_const_str_concat); +be_define_const_str(concat, "concat", 4124019837u, 0, 6, &be_const_str_remove); +be_define_const_str(remove, "remove", 3683784189u, 0, 6, &be_const_str_serial); +be_define_const_str(serial, "serial", 3687697785u, 0, 6, NULL); +be_define_const_str(SERIAL_5O2, "SERIAL_5O2", 3732325060u, 0, 10, &be_const_str__read); +be_define_const_str(_read, "_read", 346717030u, 0, 5, &be_const_str_cmd_res); +be_define_const_str(cmd_res, "cmd_res", 921166762u, 0, 7, &be_const_str_contains); +be_define_const_str(contains, "contains", 1825239352u, 0, 8, &be_const_str_imax); +be_define_const_str(imax, "imax", 3084515410u, 0, 4, &be_const_str_super); +be_define_const_str(super, "super", 4152230356u, 0, 5, &be_const_str_try); +be_define_const_str(try, "try", 2887626766u, 68, 3, NULL); +be_define_const_str(last_modified, "last_modified", 772177145u, 0, 13, &be_const_str_return); +be_define_const_str(return, "return", 2246981567u, 60, 6, NULL); +be_define_const_str(SERIAL_6N2, "SERIAL_6N2", 148562844u, 0, 10, NULL); +be_define_const_str(call, "call", 3018949801u, 0, 4, &be_const_str_resize); +be_define_const_str(resize, "resize", 3514612129u, 0, 6, NULL); +be_define_const_str(escape, "escape", 2652972038u, 0, 6, NULL); +be_define_const_str(upper, "upper", 176974407u, 0, 5, NULL); +be_define_const_str(end, "end", 1787721130u, 56, 3, NULL); +be_define_const_str(gamma8, "gamma8", 3802843830u, 0, 6, &be_const_str_memory); +be_define_const_str(memory, "memory", 2229924270u, 0, 6, &be_const_str_wifi); +be_define_const_str(wifi, "wifi", 120087624u, 0, 4, NULL); +be_define_const_str(yield, "yield", 1821831854u, 0, 5, NULL); +be_define_const_str(get_option, "get_option", 2123730033u, 0, 10, &be_const_str_init); +be_define_const_str(init, "init", 380752755u, 0, 4, &be_const_str_read); +be_define_const_str(read, "read", 3470762949u, 0, 4, NULL); +be_define_const_str(_settings_ptr, "_settings_ptr", 1825772182u, 0, 13, &be_const_str__timers); +be_define_const_str(_timers, "_timers", 2600100916u, 0, 7, &be_const_str_finish); +be_define_const_str(finish, "finish", 1494643858u, 0, 6, NULL); +be_define_const_str(__upper__, "__upper__", 3612202883u, 0, 9, &be_const_str_dump); +be_define_const_str(dump, "dump", 3663001223u, 0, 4, NULL); +be_define_const_str(save, "save", 3439296072u, 0, 4, NULL); +be_define_const_str(__lower__, "__lower__", 123855590u, 0, 9, &be_const_str_listdir); +be_define_const_str(listdir, "listdir", 2005220720u, 0, 7, NULL); +be_define_const_str(check_privileged_access, "check_privileged_access", 3692933968u, 0, 23, &be_const_str_rand); +be_define_const_str(rand, "rand", 2711325910u, 0, 4, &be_const_str_web_send); +be_define_const_str(web_send, "web_send", 2989941448u, 0, 8, NULL); +be_define_const_str(i2c_enabled, "i2c_enabled", 218388101u, 0, 11, &be_const_str_wire1); +be_define_const_str(wire1, "wire1", 3212721419u, 0, 5, NULL); +be_define_const_str(dac_voltage, "dac_voltage", 1552257222u, 0, 11, &be_const_str_imin); +be_define_const_str(imin, "imin", 2714127864u, 0, 4, &be_const_str_log10); +be_define_const_str(log10, "log10", 2346846000u, 0, 5, &be_const_str_skip); +be_define_const_str(skip, "skip", 1097563074u, 0, 4, &be_const_str_else); +be_define_const_str(else, "else", 3183434736u, 52, 4, &be_const_str_except); +be_define_const_str(except, "except", 950914032u, 69, 6, &be_const_str_nil); +be_define_const_str(nil, "nil", 228849900u, 63, 3, NULL); +be_define_const_str(resp_cmnd_error, "resp_cmnd_error", 2404088863u, 0, 15, NULL); +be_define_const_str(calldepth, "calldepth", 3122364302u, 0, 9, &be_const_str_do); +be_define_const_str(do, "do", 1646057492u, 65, 2, NULL); +be_define_const_str(__iterator__, "__iterator__", 3884039703u, 0, 12, &be_const_str_true); +be_define_const_str(true, "true", 1303515621u, 61, 4, NULL); +be_define_const_str(rad, "rad", 1358899048u, 0, 3, &be_const_str_import); +be_define_const_str(import, "import", 288002260u, 66, 6, NULL); +be_define_const_str(SERIAL_8O2, "SERIAL_8O2", 272345123u, 0, 10, &be_const_str_gamma10); +be_define_const_str(gamma10, "gamma10", 3472052483u, 0, 7, &be_const_str_elif); +be_define_const_str(elif, "elif", 3232090307u, 51, 4, NULL); +be_define_const_str(resp_cmnd, "resp_cmnd", 2869459626u, 0, 9, &be_const_str_shared_key); +be_define_const_str(shared_key, "shared_key", 2200833624u, 0, 10, &be_const_str_web_send_decimal); +be_define_const_str(web_send_decimal, "web_send_decimal", 1407210204u, 0, 16, &be_const_str_write8); +be_define_const_str(write8, "write8", 3133991532u, 0, 6, NULL); +be_define_const_str(SERIAL_5E1, "SERIAL_5E1", 1163775235u, 0, 10, &be_const_str_member); +be_define_const_str(member, "member", 719708611u, 0, 6, &be_const_str_sin); +be_define_const_str(sin, "sin", 3761252941u, 0, 3, NULL); +be_define_const_str(OneWire, "OneWire", 2298990722u, 0, 7, &be_const_str_SERIAL_7O2); +be_define_const_str(SERIAL_7O2, "SERIAL_7O2", 1840580294u, 0, 10, &be_const_str__begin_transmission); +be_define_const_str(_begin_transmission, "_begin_transmission", 2779461176u, 0, 19, &be_const_str_get_switch); +be_define_const_str(get_switch, "get_switch", 164821028u, 0, 10, &be_const_str_name); +be_define_const_str(name, "name", 2369371622u, 0, 4, &be_const_str_nan); +be_define_const_str(nan, "nan", 797905850u, 0, 3, NULL); +be_define_const_str(add, "add", 993596020u, 0, 3, &be_const_str_eth); +be_define_const_str(eth, "eth", 2191266556u, 0, 3, &be_const_str_find); +be_define_const_str(find, "find", 3186656602u, 0, 4, &be_const_str_read32); +be_define_const_str(read32, "read32", 1741276240u, 0, 6, &be_const_str_remove_cmd); +be_define_const_str(remove_cmd, "remove_cmd", 3832315702u, 0, 10, NULL); +be_define_const_str(gc, "gc", 1042313471u, 0, 2, &be_const_str_reset_search); +be_define_const_str(reset_search, "reset_search", 1350414305u, 0, 12, NULL); +be_define_const_str(content_stop, "content_stop", 658554751u, 0, 12, NULL); +be_define_const_str(counters, "counters", 4095866864u, 0, 8, &be_const_str_detect); +be_define_const_str(detect, "detect", 8884370u, 0, 6, &be_const_str_exp); +be_define_const_str(exp, "exp", 1923516200u, 0, 3, &be_const_str_on); +be_define_const_str(on, "on", 1630810064u, 0, 2, NULL); +be_define_const_str(arg, "arg", 1047474471u, 0, 3, &be_const_str_reduce); +be_define_const_str(reduce, "reduce", 2002030311u, 0, 6, &be_const_str_split); +be_define_const_str(split, "split", 2276994531u, 0, 5, &be_const_str_strftime); +be_define_const_str(strftime, "strftime", 187738851u, 0, 8, &be_const_str_raise); +be_define_const_str(raise, "raise", 1593437475u, 70, 5, NULL); +be_define_const_str(AudioOutputI2S, "AudioOutputI2S", 638031784u, 0, 14, &be_const_str_if); +be_define_const_str(if, "if", 959999494u, 50, 2, NULL); +be_define_const_str(cb_dispatch, "cb_dispatch", 1741510499u, 0, 11, &be_const_str_exec_tele); +be_define_const_str(exec_tele, "exec_tele", 1020751601u, 0, 9, &be_const_str_srand); +be_define_const_str(srand, "srand", 465518633u, 0, 5, NULL); +be_define_const_str(write_bytes, "write_bytes", 1227543792u, 0, 11, NULL); +be_define_const_str(_settings_def, "_settings_def", 3775560307u, 0, 13, NULL); +be_define_const_str(cosh, "cosh", 4099687964u, 0, 4, &be_const_str_pi); +be_define_const_str(pi, "pi", 1213090802u, 0, 2, &be_const_str_remove_rule); +be_define_const_str(remove_rule, "remove_rule", 3456211328u, 0, 11, &be_const_str_scale_uint); +be_define_const_str(scale_uint, "scale_uint", 3090811094u, 0, 10, &be_const_str_var); +be_define_const_str(var, "var", 2317739966u, 64, 3, NULL); +be_define_const_str(SERIAL_8E2, "SERIAL_8E2", 2421454473u, 0, 10, &be_const_str_acos); +be_define_const_str(acos, "acos", 1006755615u, 0, 4, &be_const_str_gen_cb); +be_define_const_str(gen_cb, "gen_cb", 3245227551u, 0, 6, &be_const_str_read_bytes); +be_define_const_str(read_bytes, "read_bytes", 3576733173u, 0, 10, NULL); +be_define_const_str(AudioFileSource, "AudioFileSource", 2959980058u, 0, 15, &be_const_str_SERIAL_5N1); +be_define_const_str(SERIAL_5N1, "SERIAL_5N1", 3313031680u, 0, 10, &be_const_str_wire); +be_define_const_str(wire, "wire", 4082753944u, 0, 4, &be_const_str_while); +be_define_const_str(while, "while", 231090382u, 53, 5, NULL); +be_define_const_str(SERIAL_7N2, "SERIAL_7N2", 1874282627u, 0, 10, &be_const_str_get_size); +be_define_const_str(get_size, "get_size", 2803644713u, 0, 8, NULL); +be_define_const_str(exec_rules, "exec_rules", 1445221092u, 0, 10, NULL); +be_define_const_str(_available, "_available", 1306196581u, 0, 10, &be_const_str_search); +be_define_const_str(search, "search", 2150836393u, 0, 6, NULL); +be_define_const_str(global, "global", 503252654u, 0, 6, NULL); +be_define_const_str(collect, "collect", 2399039025u, 0, 7, &be_const_str_input); +be_define_const_str(input, "input", 4191711099u, 0, 5, &be_const_str_response_append); +be_define_const_str(response_append, "response_append", 450346371u, 0, 15, NULL); +be_define_const_str(str, "str", 3259748752u, 0, 3, NULL); +be_define_const_str(SERIAL_6E2, "SERIAL_6E2", 317471867u, 0, 10, &be_const_str_SERIAL_7E1); +be_define_const_str(SERIAL_7E1, "SERIAL_7E1", 147718061u, 0, 10, &be_const_str_content_button); +be_define_const_str(content_button, "content_button", 1956476087u, 0, 14, NULL); +be_define_const_str(number, "number", 467038368u, 0, 6, &be_const_str_tanh); +be_define_const_str(tanh, "tanh", 153638352u, 0, 4, &be_const_str_toptr); +be_define_const_str(toptr, "toptr", 3379847454u, 0, 5, &be_const_str_write_bit); +be_define_const_str(write_bit, "write_bit", 2660990436u, 0, 9, NULL); +be_define_const_str(add_cmd, "add_cmd", 3361630879u, 0, 7, &be_const_str_select); +be_define_const_str(select, "select", 297952813u, 0, 6, &be_const_str_traceback); +be_define_const_str(traceback, "traceback", 3385188109u, 0, 9, NULL); +be_define_const_str(atan2, "atan2", 3173440503u, 0, 5, &be_const_str_loop); +be_define_const_str(loop, "loop", 3723446379u, 0, 4, &be_const_str_millis); +be_define_const_str(millis, "millis", 1214679063u, 0, 6, &be_const_str_url_encode); +be_define_const_str(url_encode, "url_encode", 528392145u, 0, 10, NULL); +be_define_const_str(_end_transmission, "_end_transmission", 3237480400u, 0, 17, &be_const_str_deinit); +be_define_const_str(deinit, "deinit", 2345559592u, 0, 6, &be_const_str_tan); be_define_const_str(tan, "tan", 2633446552u, 0, 3, NULL); -be_define_const_str(target_search, "target_search", 1947846553u, 0, 13, NULL); -be_define_const_str(abs, "abs", 709362235u, 0, 3, &be_const_str_resp_cmnd_done); -be_define_const_str(resp_cmnd_done, "resp_cmnd_done", 2601874875u, 0, 14, NULL); -be_define_const_str(eth, "eth", 2191266556u, 0, 3, NULL); -be_define_const_str(SERIAL_5O1, "SERIAL_5O1", 3782657917u, 0, 10, &be_const_str_concat); -be_define_const_str(concat, "concat", 4124019837u, 0, 6, &be_const_str_flush); -be_define_const_str(flush, "flush", 3002334877u, 0, 5, &be_const_str_get_free_heap); -be_define_const_str(get_free_heap, "get_free_heap", 625069757u, 0, 13, &be_const_str_push); -be_define_const_str(push, "push", 2272264157u, 0, 4, NULL); -be_define_const_str(compile, "compile", 1000265118u, 0, 7, &be_const_str_wire2); -be_define_const_str(wire2, "wire2", 3229499038u, 0, 5, NULL); -be_define_const_str(add_cmd, "add_cmd", 3361630879u, 0, 7, &be_const_str_atan); -be_define_const_str(atan, "atan", 108579519u, 0, 4, &be_const_str_event); -be_define_const_str(event, "event", 4264611999u, 0, 5, &be_const_str_issubclass); -be_define_const_str(issubclass, "issubclass", 4078395519u, 0, 10, &be_const_str_write_file); -be_define_const_str(write_file, "write_file", 3177658879u, 0, 10, &be_const_str_class); -be_define_const_str(class, "class", 2872970239u, 57, 5, NULL); +be_define_const_str(geti, "geti", 2381006490u, 0, 4, &be_const_str_seti); +be_define_const_str(seti, "seti", 1500556254u, 0, 4, NULL); +be_define_const_str(_buffer, "_buffer", 2044888568u, 0, 7, NULL); +be_define_const_str(atan, "atan", 108579519u, 0, 4, &be_const_str_content_flush); +be_define_const_str(content_flush, "content_flush", 214922475u, 0, 13, &be_const_str_list); +be_define_const_str(list, "list", 217798785u, 0, 4, &be_const_str_tolower); +be_define_const_str(tolower, "tolower", 1042520049u, 0, 7, NULL); +be_define_const_str(dot_len, ".len", 850842136u, 0, 4, &be_const_str__request_from); +be_define_const_str(_request_from, "_request_from", 3965148604u, 0, 13, &be_const_str_has_arg); +be_define_const_str(has_arg, "has_arg", 424878688u, 0, 7, NULL); +be_define_const_str(pow, "pow", 1479764693u, 0, 3, &be_const_str_push); +be_define_const_str(push, "push", 2272264157u, 0, 4, &be_const_str_read24); +be_define_const_str(read24, "read24", 1808533811u, 0, 6, NULL); +be_define_const_str(enabled, "enabled", 49525662u, 0, 7, &be_const_str_webclient); +be_define_const_str(webclient, "webclient", 4076389146u, 0, 9, NULL); +be_define_const_str(opt_neq, "!=", 2428715011u, 0, 2, &be_const_str_dot_p2); +be_define_const_str(dot_p2, ".p2", 232398067u, 0, 3, NULL); +be_define_const_str(Wire, "Wire", 1938276536u, 0, 4, &be_const_str_decrypt); +be_define_const_str(decrypt, "decrypt", 2886974618u, 0, 7, NULL); +be_define_const_str(floor, "floor", 3102149661u, 0, 5, &be_const_str_issubclass); +be_define_const_str(issubclass, "issubclass", 4078395519u, 0, 10, NULL); +be_define_const_str(classname, "classname", 1998589948u, 0, 9, &be_const_str_rtc); +be_define_const_str(rtc, "rtc", 1070575216u, 0, 3, NULL); +be_define_const_str(add_driver, "add_driver", 1654458371u, 0, 10, NULL); static const bstring* const m_string_table[] = { - (const bstring *)&be_const_str_SERIAL_5N1, - (const bstring *)&be_const_str__global_addr, - (const bstring *)&be_const_str_OneWire, - (const bstring *)&be_const_str_SERIAL_8O2, - (const bstring *)&be_const_str_copy, - (const bstring *)&be_const_str_tostring, - (const bstring *)&be_const_str_dot_p1, - (const bstring *)&be_const_str_read8, - (const bstring *)&be_const_str_rad, - (const bstring *)&be_const_str_load, - (const bstring *)&be_const_str_opt_add, NULL, - (const bstring *)&be_const_str_chars_in_string, - (const bstring *)&be_const_str_select, - (const bstring *)&be_const_str_global, - (const bstring *)&be_const_str_opt_eq, - (const bstring *)&be_const_str_SERIAL_8E1, - (const bstring *)&be_const_str_get_power, - (const bstring *)&be_const_str_addr, - (const bstring *)&be_const_str_dot_p, - (const bstring *)&be_const_str_add, - (const bstring *)&be_const_str_SERIAL_6N1, - (const bstring *)&be_const_str_SERIAL_8O1, - (const bstring *)&be_const_str___iterator__, - (const bstring *)&be_const_str_available, - (const bstring *)&be_const_str__drivers, - (const bstring *)&be_const_str_opt_call, - (const bstring *)&be_const_str_SERIAL_6E2, - (const bstring *)&be_const_str_classname, - (const bstring *)&be_const_str_remove, - (const bstring *)&be_const_str_begin, - (const bstring *)&be_const_str_content_stop, - (const bstring *)&be_const_str_reset, - NULL, - (const bstring *)&be_const_str_clear, - (const bstring *)&be_const_str_SERIAL_5E1, - (const bstring *)&be_const_str_setitem, - (const bstring *)&be_const_str_stop, - (const bstring *)&be_const_str_AES_GCM, - (const bstring *)&be_const_str_exec_cmd, - (const bstring *)&be_const_str_ceil, - (const bstring *)&be_const_str_call, - (const bstring *)&be_const_str_cmd_res, - NULL, - NULL, - (const bstring *)&be_const_str_opt_connect, - (const bstring *)&be_const_str_SERIAL_6E1, - (const bstring *)&be_const_str__cb, - (const bstring *)&be_const_str_AudioOutput, - (const bstring *)&be_const_str_SERIAL_6O2, - (const bstring *)&be_const_str_detect, - (const bstring *)&be_const_str_depower, - (const bstring *)&be_const_str_add_header, - (const bstring *)&be_const_str_pow, - (const bstring *)&be_const_str_SERIAL_5E2, - (const bstring *)&be_const_str_get, - (const bstring *)&be_const_str_dot_len, - (const bstring *)&be_const_str_SERIAL_5N2, - (const bstring *)&be_const_str_AudioFileSource, - (const bstring *)&be_const_str_digital_write, - NULL, - (const bstring *)&be_const_str_char, - (const bstring *)&be_const_str_AudioGenerator, - (const bstring *)&be_const_str_byte, - (const bstring *)&be_const_str_dot_size, - (const bstring *)&be_const_str_list, - NULL, - (const bstring *)&be_const_str_SERIAL_7N2, - (const bstring *)&be_const_str_Tasmota, - (const bstring *)&be_const_str_read, - (const bstring *)&be_const_str___lower__, - (const bstring *)&be_const_str_POST, - (const bstring *)&be_const_str_deinit, - (const bstring *)&be_const_str_SERIAL_8E2, - (const bstring *)&be_const_str_isnan, - (const bstring *)&be_const_str_arg_name, - (const bstring *)&be_const_str_get_light, - NULL, - NULL, - (const bstring *)&be_const_str_sqrt, - (const bstring *)&be_const_str__end_transmission, - (const bstring *)&be_const_str_exec_tele, - (const bstring *)&be_const_str_format, - NULL, - (const bstring *)&be_const_str_SERIAL_7E2, - NULL, - (const bstring *)&be_const_str_SERIAL_7N1, - (const bstring *)&be_const_str_content_button, - (const bstring *)&be_const_str_AudioGeneratorMP3, - (const bstring *)&be_const_str_fromptr, - (const bstring *)&be_const_str_geti, - (const bstring *)&be_const_str_assert, - (const bstring *)&be_const_str_time_str, - (const bstring *)&be_const_str_exists, - (const bstring *)&be_const_str_seti, - (const bstring *)&be_const_str_acos, - (const bstring *)&be_const_str_find_op, - NULL, - (const bstring *)&be_const_str_isinstance, - (const bstring *)&be_const_str_cb_dispatch, - (const bstring *)&be_const_str_SERIAL_5O2, - (const bstring *)&be_const_str_, - (const bstring *)&be_const_str_dac_voltage, - (const bstring *)&be_const_str_add_rule, - (const bstring *)&be_const_str_AudioOutputI2S, - (const bstring *)&be_const_str__write, - (const bstring *)&be_const_str_resp_cmnd, - NULL, - NULL, - (const bstring *)&be_const_str_content_start, - (const bstring *)&be_const_str_memory, - (const bstring *)&be_const_str_EC_C25519, - (const bstring *)&be_const_str_str, - (const bstring *)&be_const_str_get_option, - (const bstring *)&be_const_str_dot_w, - (const bstring *)&be_const_str_SERIAL_7O1, - (const bstring *)&be_const_str__timers, - NULL, - NULL, - (const bstring *)&be_const_str_GET, - (const bstring *)&be_const_str_break, - (const bstring *)&be_const_str__global_def, - (const bstring *)&be_const_str_find, - NULL, - (const bstring *)&be_const_str_SERIAL_6N2, - (const bstring *)&be_const_str_module, - (const bstring *)&be_const_str_var, - (const bstring *)&be_const_str_content_send_style, - (const bstring *)&be_const_str_asstring, - (const bstring *)&be_const_str_get_string, - (const bstring *)&be_const_str_encrypt, - (const bstring *)&be_const_str_opt_neq, - (const bstring *)&be_const_str_exec_rules, - (const bstring *)&be_const_str_AudioFileSourceFS, - (const bstring *)&be_const_str_SERIAL_7O2, - NULL, - (const bstring *)&be_const_str__ptr, + (const bstring *)&be_const_str_setmember, + (const bstring *)&be_const_str_hex, (const bstring *)&be_const_str_arch, + (const bstring *)&be_const_str_top, + (const bstring *)&be_const_str_content_start, + (const bstring *)&be_const_str_compile, + (const bstring *)&be_const_str_arg_name, + (const bstring *)&be_const_str_insert, + (const bstring *)&be_const_str_open, NULL, - (const bstring *)&be_const_str_cmd, - (const bstring *)&be_const_str_nil, - (const bstring *)&be_const_str_SERIAL_7E1, - (const bstring *)&be_const_str_calldepth, + (const bstring *)&be_const_str_ctypes_bytes, + (const bstring *)&be_const_str_reset, + (const bstring *)&be_const_str_POST, + (const bstring *)&be_const_str_available, NULL, - (const bstring *)&be_const_str_counters, - (const bstring *)&be_const_str__rules, - (const bstring *)&be_const_str_codedump, - (const bstring *)&be_const_str_dot_p2, - NULL, - (const bstring *)&be_const_str_erase, - (const bstring *)&be_const_str_gamma8, - NULL, - (const bstring *)&be_const_str_SERIAL_6O1, + (const bstring *)&be_const_str__get_cb, + (const bstring *)&be_const_str_get_string, + (const bstring *)&be_const_str_asstring, + (const bstring *)&be_const_str_static, + (const bstring *)&be_const_str_AES_GCM, + (const bstring *)&be_const_str_close, + (const bstring *)&be_const_str_find_op, + (const bstring *)&be_const_str_get, + (const bstring *)&be_const_str_print, (const bstring *)&be_const_str_target_search, NULL, - (const bstring *)&be_const_str_abs, - (const bstring *)&be_const_str_eth, + (const bstring *)&be_const_str__ccmd, + (const bstring *)&be_const_str_allocated, + (const bstring *)&be_const_str_GET, + (const bstring *)&be_const_str_SERIAL_8E1, + (const bstring *)&be_const_str_assert, + (const bstring *)&be_const_str_codedump, + (const bstring *)&be_const_str_opt_connect, + (const bstring *)&be_const_str_update, + NULL, + (const bstring *)&be_const_str__cmd, (const bstring *)&be_const_str_SERIAL_5O1, - (const bstring *)&be_const_str_compile, - (const bstring *)&be_const_str_add_cmd + (const bstring *)&be_const_str_SERIAL_7E2, + (const bstring *)&be_const_str_SERIAL_6N1, + (const bstring *)&be_const_str_Tasmota, + (const bstring *)&be_const_str_time_reached, + (const bstring *)&be_const_str_chars_in_string, + (const bstring *)&be_const_str_add_rule, + NULL, + NULL, + (const bstring *)&be_const_str_SERIAL_8O1, + (const bstring *)&be_const_str_AudioFileSourceFS, + (const bstring *)&be_const_str_AudioGenerator, + (const bstring *)&be_const_str__global_addr, + (const bstring *)&be_const_str_dot_w, + (const bstring *)&be_const_str_MD5, + (const bstring *)&be_const_str_break, + (const bstring *)&be_const_str_digital_write, + (const bstring *)&be_const_str_asin, + (const bstring *)&be_const_str__def, + (const bstring *)&be_const_str_set_light, + (const bstring *)&be_const_str_arg_size, + NULL, + (const bstring *)&be_const_str_opt_eq, + (const bstring *)&be_const_str_kv, + (const bstring *)&be_const_str_tostring, + (const bstring *)&be_const_str_format, + (const bstring *)&be_const_str_log, + (const bstring *)&be_const_str_SERIAL_7N1, + (const bstring *)&be_const_str_stop, + (const bstring *)&be_const_str_count, + (const bstring *)&be_const_str_byte, + (const bstring *)&be_const_str_fromstring, + (const bstring *)&be_const_str_cmd, + (const bstring *)&be_const_str_SERIAL_6E1, + (const bstring *)&be_const_str_EC_C25519, + (const bstring *)&be_const_str_read12, + (const bstring *)&be_const_str__write, + (const bstring *)&be_const_str_opt_call, + NULL, + (const bstring *)&be_const_str_AudioGeneratorMP3, + (const bstring *)&be_const_str_ctypes_bytes_dyn, + (const bstring *)&be_const_str_set_auth, + (const bstring *)&be_const_str_, + (const bstring *)&be_const_str_public_key, + (const bstring *)&be_const_str_get_power, + (const bstring *)&be_const_str_opt_add, + (const bstring *)&be_const_str_getbits, + (const bstring *)&be_const_str_dot_p1, + (const bstring *)&be_const_str_read8, + (const bstring *)&be_const_str_AudioGeneratorWAV, + (const bstring *)&be_const_str__global_def, + (const bstring *)&be_const_str__ptr, + NULL, + (const bstring *)&be_const_str_pin, + (const bstring *)&be_const_str_dot_p, + (const bstring *)&be_const_str_I2C_Driver, + (const bstring *)&be_const_str_SERIAL_8N1, + (const bstring *)&be_const_str_SERIAL_5O2, + (const bstring *)&be_const_str_last_modified, + (const bstring *)&be_const_str_SERIAL_6N2, + (const bstring *)&be_const_str_call, + (const bstring *)&be_const_str_escape, + (const bstring *)&be_const_str_upper, + (const bstring *)&be_const_str_end, + NULL, + (const bstring *)&be_const_str_gamma8, + NULL, + (const bstring *)&be_const_str_yield, + (const bstring *)&be_const_str_get_option, + (const bstring *)&be_const_str__settings_ptr, + (const bstring *)&be_const_str___upper__, + (const bstring *)&be_const_str_save, + NULL, + (const bstring *)&be_const_str___lower__, + NULL, + (const bstring *)&be_const_str_check_privileged_access, + (const bstring *)&be_const_str_i2c_enabled, + (const bstring *)&be_const_str_dac_voltage, + (const bstring *)&be_const_str_resp_cmnd_error, + (const bstring *)&be_const_str_calldepth, + (const bstring *)&be_const_str___iterator__, + (const bstring *)&be_const_str_rad, + (const bstring *)&be_const_str_SERIAL_8O2, + (const bstring *)&be_const_str_resp_cmnd, + (const bstring *)&be_const_str_SERIAL_5E1, + (const bstring *)&be_const_str_OneWire, + NULL, + (const bstring *)&be_const_str_add, + (const bstring *)&be_const_str_gc, + NULL, + (const bstring *)&be_const_str_content_stop, + (const bstring *)&be_const_str_counters, + (const bstring *)&be_const_str_arg, + (const bstring *)&be_const_str_AudioOutputI2S, + (const bstring *)&be_const_str_cb_dispatch, + (const bstring *)&be_const_str_write_bytes, + (const bstring *)&be_const_str__settings_def, + (const bstring *)&be_const_str_cosh, + (const bstring *)&be_const_str_SERIAL_8E2, + (const bstring *)&be_const_str_AudioFileSource, + (const bstring *)&be_const_str_SERIAL_7N2, + (const bstring *)&be_const_str_exec_rules, + (const bstring *)&be_const_str__available, + (const bstring *)&be_const_str_global, + (const bstring *)&be_const_str_collect, + (const bstring *)&be_const_str_str, + (const bstring *)&be_const_str_SERIAL_6E2, + (const bstring *)&be_const_str_number, + (const bstring *)&be_const_str_add_cmd, + NULL, + (const bstring *)&be_const_str_atan2, + (const bstring *)&be_const_str__end_transmission, + NULL, + (const bstring *)&be_const_str_geti, + NULL, + (const bstring *)&be_const_str__buffer, + (const bstring *)&be_const_str_atan, + (const bstring *)&be_const_str_dot_len, + (const bstring *)&be_const_str_pow, + (const bstring *)&be_const_str_enabled, + (const bstring *)&be_const_str_opt_neq, + (const bstring *)&be_const_str_Wire, + (const bstring *)&be_const_str_floor, + (const bstring *)&be_const_str_classname, + (const bstring *)&be_const_str_add_driver }; static const struct bconststrtab m_const_string_table = { - .size = 160, - .count = 321, + .size = 162, + .count = 324, .table = m_string_table }; diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_tasmota.h b/lib/libesp32/Berry/generate/be_fixed_be_class_tasmota.h index 34b9c0a05..a61b9a363 100644 --- a/lib/libesp32/Berry/generate/be_fixed_be_class_tasmota.h +++ b/lib/libesp32/Berry/generate/be_fixed_be_class_tasmota.h @@ -1,91 +1,92 @@ #include "be_constobj.h" static be_define_const_map_slots(be_class_tasmota_map) { - { be_const_key(resp_cmnd_done, -1), be_const_func(l_respCmndDone) }, - { be_const_key(settings, 70), be_const_var(0) }, - { be_const_key(set_light, -1), be_const_closure(set_light_closure) }, - { be_const_key(gc, 35), be_const_closure(gc_closure) }, - { be_const_key(add_cmd, -1), be_const_closure(add_cmd_closure) }, - { be_const_key(try_rule, -1), be_const_closure(try_rule_closure) }, - { be_const_key(publish, 20), be_const_func(l_publish) }, - { be_const_key(_settings_ptr, 28), be_const_comptr(&Settings) }, - { be_const_key(exec_tele, 36), be_const_closure(exec_tele_closure) }, - { be_const_key(delay, -1), be_const_func(l_delay) }, - { be_const_key(_drivers, -1), be_const_var(1) }, - { be_const_key(find_key_i, -1), be_const_closure(find_key_i_closure) }, - { be_const_key(resp_cmnd_failed, -1), be_const_func(l_respCmndFailed) }, - { be_const_key(wire2, 64), be_const_var(2) }, - { be_const_key(gen_cb, 56), be_const_closure(gen_cb_closure) }, - { be_const_key(resp_cmnd_str, -1), be_const_func(l_respCmndStr) }, - { be_const_key(_timers, 25), be_const_var(3) }, - { be_const_key(kv, -1), be_const_closure(kv_closure) }, - { be_const_key(set_power, -1), be_const_func(l_setpower) }, - { be_const_key(cmd, 38), be_const_closure(cmd_closure) }, - { be_const_key(global, -1), be_const_var(4) }, - { be_const_key(response_append, -1), be_const_func(l_respAppend) }, - { be_const_key(_get_cb, -1), be_const_func(l_get_cb) }, - { be_const_key(time_reached, -1), be_const_func(l_timereached) }, - { be_const_key(wifi, 19), be_const_func(l_wifi) }, - { be_const_key(rtc, -1), be_const_func(l_rtc) }, - { be_const_key(i2c_enabled, 8), be_const_func(l_i2cenabled) }, - { be_const_key(publish_result, 34), be_const_func(l_publish_result) }, - { be_const_key(_settings_def, -1), be_const_comptr(&be_tasmota_settings_struct) }, - { be_const_key(yield, 6), be_const_func(l_yield) }, - { be_const_key(init, -1), be_const_closure(init_closure) }, - { be_const_key(eth, -1), be_const_func(l_eth) }, - { be_const_key(get_free_heap, -1), be_const_func(l_getFreeHeap) }, - { be_const_key(get_option, -1), be_const_func(l_getoption) }, - { be_const_key(get_power, -1), be_const_func(l_getpower) }, - { be_const_key(run_deferred, -1), be_const_closure(run_deferred_closure) }, - { be_const_key(get_light, 11), be_const_closure(get_light_closure) }, - { be_const_key(cmd_res, -1), be_const_var(5) }, - { be_const_key(event, -1), be_const_closure(event_closure) }, - { be_const_key(load, -1), be_const_closure(load_closure) }, - { be_const_key(remove_timer, -1), be_const_closure(remove_timer_closure) }, - { be_const_key(wire_scan, -1), be_const_closure(wire_scan_closure) }, - { be_const_key(_cb, 50), be_const_var(6) }, - { be_const_key(remove_driver, 67), be_const_closure(remove_driver_closure) }, - { be_const_key(wire1, 61), be_const_var(7) }, - { be_const_key(memory, -1), be_const_func(l_memory) }, - { be_const_key(_global_addr, -1), be_const_comptr(&TasmotaGlobal) }, - { be_const_key(time_dump, -1), be_const_func(l_time_dump) }, - { be_const_key(_ccmd, -1), be_const_var(8) }, - { be_const_key(exec_cmd, 39), be_const_closure(exec_cmd_closure) }, - { be_const_key(exec_rules, 68), be_const_closure(exec_rules_closure) }, - { be_const_key(resp_cmnd, 14), be_const_func(l_respCmnd) }, - { be_const_key(remove_cmd, -1), be_const_closure(remove_cmd_closure) }, - { be_const_key(remove_rule, 69), be_const_closure(remove_rule_closure) }, - { be_const_key(web_send_decimal, -1), be_const_func(l_webSendDecimal) }, - { be_const_key(_rules, 41), be_const_var(9) }, - { be_const_key(strftime, 59), be_const_func(l_strftime) }, - { be_const_key(chars_in_string, -1), be_const_closure(chars_in_string_closure) }, - { be_const_key(set_timer, -1), be_const_closure(set_timer_closure) }, - { be_const_key(_global_def, -1), be_const_comptr(&be_tasmota_global_struct) }, - { be_const_key(resolvecmnd, -1), be_const_func(l_resolveCmnd) }, + { be_const_key(exec_rules, 20), be_const_closure(exec_rules_closure) }, + { be_const_key(publish_result, 75), be_const_func(l_publish_result) }, { be_const_key(scale_uint, -1), be_const_func(l_scaleuint) }, - { be_const_key(time_str, -1), be_const_closure(time_str_closure) }, - { be_const_key(millis, 48), be_const_func(l_millis) }, - { be_const_key(resp_cmnd_error, -1), be_const_func(l_respCmndError) }, - { be_const_key(arch, -1), be_const_func(l_arch) }, - { be_const_key(log, -1), be_const_func(l_logInfo) }, - { be_const_key(add_rule, -1), be_const_closure(add_rule_closure) }, - { be_const_key(_cmd, 17), be_const_func(l_cmd) }, - { be_const_key(get_switch, -1), be_const_func(l_getswitch) }, + { be_const_key(strftime, 6), be_const_func(l_strftime) }, + { be_const_key(remove_driver, -1), be_const_closure(remove_driver_closure) }, + { be_const_key(get_free_heap, -1), be_const_func(l_getFreeHeap) }, + { be_const_key(time_dump, -1), be_const_func(l_time_dump) }, + { be_const_key(add_driver, 37), be_const_closure(add_driver_closure) }, { be_const_key(find_op, -1), be_const_closure(find_op_closure) }, - { be_const_key(add_driver, 3), be_const_closure(add_driver_closure) }, - { be_const_key(save, 65), be_const_func(l_save) }, - { be_const_key(web_send, -1), be_const_func(l_webSend) }, + { be_const_key(arch, 38), be_const_func(l_arch) }, + { be_const_key(eth, 26), be_const_func(l_eth) }, + { be_const_key(response_append, -1), be_const_func(l_respAppend) }, + { be_const_key(_timers, -1), be_const_var(0) }, + { be_const_key(try_rule, -1), be_const_closure(try_rule_closure) }, + { be_const_key(_settings_ptr, -1), be_const_comptr(&Settings) }, + { be_const_key(resp_cmnd_error, -1), be_const_func(l_respCmndError) }, + { be_const_key(publish, -1), be_const_func(l_publish) }, + { be_const_key(time_reached, 32), be_const_func(l_timereached) }, + { be_const_key(_get_cb, -1), be_const_func(l_get_cb) }, + { be_const_key(wire1, 27), be_const_var(1) }, + { be_const_key(rtc, 43), be_const_func(l_rtc) }, + { be_const_key(web_send_decimal, -1), be_const_func(l_webSendDecimal) }, + { be_const_key(cmd_res, -1), be_const_var(2) }, + { be_const_key(add_rule, -1), be_const_closure(add_rule_closure) }, + { be_const_key(delay, 40), be_const_func(l_delay) }, + { be_const_key(_global_addr, -1), be_const_comptr(&TasmotaGlobal) }, + { be_const_key(set_light, -1), be_const_closure(set_light_closure) }, + { be_const_key(add_cmd, 74), be_const_closure(add_cmd_closure) }, + { be_const_key(global, -1), be_const_var(3) }, + { be_const_key(get_power, -1), be_const_func(l_getpower) }, + { be_const_key(wire2, -1), be_const_var(4) }, + { be_const_key(cmd, -1), be_const_closure(cmd_closure) }, + { be_const_key(get_option, 48), be_const_func(l_getoption) }, + { be_const_key(set_power, -1), be_const_func(l_setpower) }, + { be_const_key(wd, 28), be_const_var(5) }, + { be_const_key(remove_timer, -1), be_const_closure(remove_timer_closure) }, + { be_const_key(wire_scan, 61), be_const_closure(wire_scan_closure) }, + { be_const_key(_settings_def, -1), be_const_comptr(&be_tasmota_settings_struct) }, + { be_const_key(exec_tele, 69), be_const_closure(exec_tele_closure) }, + { be_const_key(gen_cb, -1), be_const_closure(gen_cb_closure) }, + { be_const_key(chars_in_string, 66), be_const_closure(chars_in_string_closure) }, + { be_const_key(log, -1), be_const_func(l_logInfo) }, + { be_const_key(find_key_i, -1), be_const_closure(find_key_i_closure) }, + { be_const_key(get_light, -1), be_const_closure(get_light_closure) }, + { be_const_key(time_str, -1), be_const_closure(time_str_closure) }, + { be_const_key(_rules, 73), be_const_var(6) }, + { be_const_key(remove_cmd, 50), be_const_closure(remove_cmd_closure) }, + { be_const_key(_cb, -1), be_const_var(7) }, + { be_const_key(_ccmd, -1), be_const_var(8) }, + { be_const_key(i2c_enabled, 53), be_const_func(l_i2cenabled) }, + { be_const_key(resp_cmnd_str, -1), be_const_func(l_respCmndStr) }, + { be_const_key(init, -1), be_const_closure(init_closure) }, + { be_const_key(save, 10), be_const_func(l_save) }, + { be_const_key(set_timer, -1), be_const_closure(set_timer_closure) }, + { be_const_key(resp_cmnd, -1), be_const_func(l_respCmnd) }, + { be_const_key(resp_cmnd_done, -1), be_const_func(l_respCmndDone) }, + { be_const_key(get_switch, 21), be_const_func(l_getswitch) }, + { be_const_key(load, -1), be_const_closure(load_closure) }, + { be_const_key(_cmd, 72), be_const_func(l_cmd) }, + { be_const_key(event, -1), be_const_closure(event_closure) }, + { be_const_key(run_deferred, -1), be_const_closure(run_deferred_closure) }, + { be_const_key(web_send, 1), be_const_func(l_webSend) }, + { be_const_key(memory, -1), be_const_func(l_memory) }, { be_const_key(cb_dispatch, -1), be_const_closure(cb_dispatch_closure) }, + { be_const_key(remove_rule, 36), be_const_closure(remove_rule_closure) }, + { be_const_key(resolvecmnd, -1), be_const_func(l_resolveCmnd) }, + { be_const_key(wifi, -1), be_const_func(l_wifi) }, + { be_const_key(exec_cmd, -1), be_const_closure(exec_cmd_closure) }, + { be_const_key(settings, 60), be_const_var(9) }, + { be_const_key(_global_def, -1), be_const_comptr(&be_tasmota_global_struct) }, + { be_const_key(resp_cmnd_failed, -1), be_const_func(l_respCmndFailed) }, + { be_const_key(gc, -1), be_const_closure(gc_closure) }, + { be_const_key(yield, -1), be_const_func(l_yield) }, + { be_const_key(_drivers, -1), be_const_var(10) }, + { be_const_key(millis, -1), be_const_func(l_millis) }, + { be_const_key(kv, -1), be_const_closure(kv_closure) }, }; static be_define_const_map( be_class_tasmota_map, - 75 + 76 ); BE_EXPORT_VARIABLE be_define_const_class( be_class_tasmota, - 10, + 11, NULL, Tasmota ); diff --git a/lib/libesp32/Berry/generate/be_fixed_string.h b/lib/libesp32/Berry/generate/be_fixed_string.h index eb1e5cf58..9710edd7f 100644 --- a/lib/libesp32/Berry/generate/be_fixed_string.h +++ b/lib/libesp32/Berry/generate/be_fixed_string.h @@ -1,20 +1,22 @@ #include "be_constobj.h" static be_define_const_map_slots(m_libstring_map) { - { be_const_key(tolower, -1), be_const_func(str_tolower) }, - { be_const_key(count, -1), be_const_func(str_count) }, - { be_const_key(hex, -1), be_const_func(str_i2hex) }, - { be_const_key(split, 5), be_const_func(str_split) }, + { be_const_key(char, -1), be_const_func(str_char) }, + { be_const_key(tr, -1), be_const_func(str_tr) }, + { be_const_key(count, 4), be_const_func(str_count) }, + { be_const_key(format, 7), be_const_func(str_format) }, + { be_const_key(escape, -1), be_const_func(str_escape) }, { be_const_key(byte, -1), be_const_func(str_byte) }, - { be_const_key(char, 6), be_const_func(str_char) }, - { be_const_key(toupper, 1), be_const_func(str_toupper) }, + { be_const_key(toupper, -1), be_const_func(str_toupper) }, + { be_const_key(hex, -1), be_const_func(str_i2hex) }, { be_const_key(find, -1), be_const_func(str_find) }, - { be_const_key(format, -1), be_const_func(str_format) }, + { be_const_key(split, 1), be_const_func(str_split) }, + { be_const_key(tolower, -1), be_const_func(str_tolower) }, }; static be_define_const_map( m_libstring_map, - 9 + 11 ); static be_define_const_module( diff --git a/lib/libesp32/Berry/src/be_solidifylib.c b/lib/libesp32/Berry/src/be_solidifylib.c index d72e3aff5..1562c3bb6 100644 --- a/lib/libesp32/Berry/src/be_solidifylib.c +++ b/lib/libesp32/Berry/src/be_solidifylib.c @@ -25,7 +25,7 @@ extern const bclass be_class_map; #include #ifndef INST_BUF_SIZE -#define INST_BUF_SIZE 96 +#define INST_BUF_SIZE 288 #endif #define logbuf(...) snprintf(__lbuf, sizeof(__lbuf), __VA_ARGS__) @@ -115,13 +115,15 @@ static void m_solidify_bvalue(bvm *vm, bvalue * value, const char *classname, co break; case BE_STRING: { - logfmt("be_nested_string(\""); - be_writestring(str(var_tostr(value))); size_t len = strlen(str(var_tostr(value))); if (len >= 255) { be_raise(vm, "internal_error", "Strings greater than 255 chars not supported yet"); } - logfmt("\", %i, %zu)", be_strhash(var_tostr(value)), len >= 255 ? 255 : len); + be_pushstring(vm, str(var_tostr(value))); + be_toescape(vm, -1, 'u'); + logfmt("be_nested_string(%s", be_tostring(vm, -1)); + be_pop(vm, 1); + logfmt(", %i, %zu)", be_strhash(var_tostr(value)), len >= 255 ? 255 : len); } break; case BE_CLOSURE: diff --git a/lib/libesp32/Berry/src/be_strlib.c b/lib/libesp32/Berry/src/be_strlib.c index 3a079fa22..e82ec3cf2 100644 --- a/lib/libesp32/Berry/src/be_strlib.c +++ b/lib/libesp32/Berry/src/be_strlib.c @@ -788,6 +788,53 @@ static int str_toupper(bvm *vm) { return str_touplower(vm, btrue); } +static int str_tr(bvm *vm) +{ + if (be_top(vm) == 3 && be_isstring(vm, 1) && be_isstring(vm, 2) && be_isstring(vm, 3)) { + const char *p, *s = be_tostring(vm, 1); + const char *t1 = be_tostring(vm, 2); + const char *t2 = be_tostring(vm, 3); + if (strlen(t2) < strlen(t1)) { + be_raise(vm, "value_error", "invalid translation pattern"); + } + size_t len = (size_t)be_strlen(vm, 1); + char *buf, *q; + buf = be_pushbuffer(vm, len); + /* convert each char */ + for (p = s, q = buf; *p != '\0'; ++p, ++q) { + const char *p1, *p2; + *q = *p; /* default to no change */ + for (p1=t1, p2=t2; *p1 != '\0'; ++p1, ++p2) { + if (*p == *p1) { + *q = *p2; + break; + } + } + } + be_pushnstring(vm, buf, len); /* make escape string from buffer */ + be_remove(vm, 2); /* remove buffer */ + be_return(vm); + } + be_return_nil(vm); +} + +static int str_escape(bvm *vm) +{ + int top = be_top(vm); + if (top >= 1 && be_isstring(vm, 1)) { + int quote = 'u'; + if (top >= 2 && be_isbool(vm, 2)) { + if (be_tobool(vm, 1)) { + quote = 'x'; + } + } + be_tostring(vm, 1); + be_toescape(vm, 1, quote); + be_pushvalue(vm, 1); + be_return(vm); + } + be_return_nil(vm); +} #if !BE_USE_PRECOMPILED_OBJECT be_native_module_attr_table(string) { @@ -800,6 +847,8 @@ be_native_module_attr_table(string) { be_native_module_function("char", str_char), be_native_module_function("tolower", str_tolower), be_native_module_function("toupper", str_toupper), + be_native_module_function("tr", str_tr), + be_native_module_function("escape", str_escape), }; be_define_native_module(string, NULL); @@ -815,6 +864,8 @@ module string (scope: global, depend: BE_USE_STRING_MODULE) { char, func(str_char) tolower, func(str_tolower) toupper, func(str_toupper) + tr, func(str_tr) + escape, func(str_escape) } @const_object_info_end */ #include "../generate/be_fixed_string.h" diff --git a/lib/libesp32/Zip-readonly-FS/src/ZipReadFS.cpp b/lib/libesp32/Zip-readonly-FS/src/ZipReadFS.cpp index a7282c128..61e83b683 100644 --- a/lib/libesp32/Zip-readonly-FS/src/ZipReadFS.cpp +++ b/lib/libesp32/Zip-readonly-FS/src/ZipReadFS.cpp @@ -371,7 +371,7 @@ bool ZipArchive::parse(void) { entry.last_mod = dos2unixtime((header.last_mod_date << 16) | header.last_mod_time); offset += header.size_uncompressed; - AddLog(LOG_LEVEL_DEBUG, "ZIP: found file '%s' (%i bytes - offset %i) - next entry %i", &fname[0], header.size_uncompressed, entry.file_start, offset); + AddLog(LOG_LEVEL_DEBUG_MORE, "ZIP: found file '%s' (%i bytes - offset %i) - next entry %i", &fname[0], header.size_uncompressed, entry.file_start, offset); } return true; diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 432532e6e..f8a78dc96 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -990,6 +990,7 @@ //#define USE_IBEACON_ESP32 //#define USE_WEBCAM // Add support for webcam +// #define USE_AUTOCONF // Enable Esp32 autoconf feature, requires USE_BERRY and USE_WEBCLIENT_HTTPS (12KB Flash) #define USE_BERRY // Enable Berry scripting language #define USE_BERRY_PYTHON_COMPAT // Enable by default `import python_compat` #define USE_BERRY_TIMEOUT 4000 // Timeout in ms, will raise an exception if running time exceeds this timeout @@ -1091,6 +1092,19 @@ #error "Select either USE_RULES or USE_SCRIPT. They can't both be used at the same time" #endif +/*********************************************************************************************\ + * Post-process compile options for Autoconf +\*********************************************************************************************/ + +#if defined(USE_AUTOCONF) + #ifndef USE_BERRY + #define USE_BERRY + #endif + #ifndef USE_WEBCLIENT_HTTPS + #define USE_WEBCLIENT_HTTPS + #endif +#endif // USE_AUTOCONF + /*********************************************************************************************\ * Post-process compile options for TLS \*********************************************************************************************/ diff --git a/tasmota/xdrv_13_display.ino b/tasmota/xdrv_13_display.ino index da4439f61..bcf545bc5 100755 --- a/tasmota/xdrv_13_display.ino +++ b/tasmota/xdrv_13_display.ino @@ -67,7 +67,7 @@ struct MULTI_DISP { uint8_t used; } displays[MAX_MULTI_DISPLAYS]; uint8_t cur_display; -Renderer *Init_uDisplay(const char *desc, int8_t cs); +Renderer *Init_uDisplay(const char *desc, int8_t cs = -1); void Set_display(uint8_t index) { displays[index].display = renderer; @@ -631,7 +631,7 @@ void DisplayText(void) srot = Settings->display_rotate; Settings->display_rotate = rot; } - renderer = Init_uDisplay(fdesc, -1); + renderer = Init_uDisplay(fdesc); if (rot >= 0) { Settings->display_rotate = srot; } diff --git a/tasmota/xdrv_52_0_berry_struct.ino b/tasmota/xdrv_52_0_berry_struct.ino index 74ae1eee7..1c3991b80 100644 --- a/tasmota/xdrv_52_0_berry_struct.ino +++ b/tasmota/xdrv_52_0_berry_struct.ino @@ -21,6 +21,7 @@ #ifdef USE_BERRY #include +#include #define BERRY_CONSOLE_CMD_DELIMITER "\x01" diff --git a/tasmota/xdrv_52_3_berry_display.ino b/tasmota/xdrv_52_3_berry_display.ino new file mode 100644 index 000000000..cb5b47846 --- /dev/null +++ b/tasmota/xdrv_52_3_berry_display.ino @@ -0,0 +1,63 @@ +/* + xdrv_52_3_berry_display.ino - Berry scripting language, native fucnctions + + Copyright (C) 2021 Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + +#ifdef USE_BERRY +#ifdef USE_DISPLAY + +#include + +#ifdef USE_UNIVERSAL_DISPLAY +Renderer *Init_uDisplay(const char *desc, int8_t cs = -1); +#endif // USE_UNIVERSAL_DISPLAY + +/*********************************************************************************************\ + * Native functions mapped to Berry functions + * + * import display + * display.start(string) -> comptr or nil if failed + * +\*********************************************************************************************/ +extern "C" { + + int be_disp_start(bvm *vm); + int be_disp_start(bvm *vm) { +#ifdef USE_UNIVERSAL_DISPLAY + int32_t argc = be_top(vm); // Get the number of arguments + if (argc >= 1 && be_isstring(vm, 1)) { + const char * desc = be_tostring(vm, 1); + // remove all objects on stack to avoid warnings in subsequent calls to Berry + be_pop(vm, argc); + Renderer * renderer = Init_uDisplay(desc); + if (renderer) { + be_pushcomptr(vm, renderer); + } else { + be_pushnil(vm); + } + be_return(vm); + } + be_raise(vm, kTypeError, nullptr); +#else // USE_UNIVERSAL_DISPLAY + be_raise(vm, "internal_error", "universal display driver not present"); +#endif // USE_UNIVERSAL_DISPLAY + } +} + +#endif // USE_DISPLAY +#endif // USE_BERRY diff --git a/tasmota/xdrv_52_7_berry_embedded.ino b/tasmota/xdrv_52_7_berry_embedded.ino index 5450de6a9..4d16ced05 100644 --- a/tasmota/xdrv_52_7_berry_embedded.ino +++ b/tasmota/xdrv_52_7_berry_embedded.ino @@ -43,6 +43,11 @@ const char berry_prog[] = "def log(m,l) tasmota.log(m,l) end " "def load(f) return tasmota.load(f) end " +#ifdef USE_AUTOCONF + // autoconf + "import autoconf " +#endif // USE_AUTOCONF + #ifdef USE_LVGL "import lv " // create the '_lvgl' global singleton diff --git a/tasmota/xdrv_52_9_berry.ino b/tasmota/xdrv_52_9_berry.ino index 61879a761..751dec823 100644 --- a/tasmota/xdrv_52_9_berry.ino +++ b/tasmota/xdrv_52_9_berry.ino @@ -241,6 +241,34 @@ int32_t callBerryEventDispatcher(const char *type, const char *cmd, int32_t idx, return ret; } +// call a method in autoconf +int32_t callBerryAutoconf(const char * method) { + int32_t ret = 0; + bvm *vm = berry.vm; + + if (nullptr == vm) { return ret; } + checkBeTop(); + be_getglobal(vm, "autoconf"); + if (!be_isnil(vm, -1)) { + be_getmethod(vm, -1, method); + if (!be_isnil(vm, -1)) { + be_pushvalue(vm, -2); + BrTimeoutStart(); + ret = be_pcall(vm, 1); // 1 arg + BrTimeoutReset(); + if (ret != 0) { + BerryDumpErrorAndClear(vm, false); // log in Tasmota console only + return ret; + } + be_pop(vm, 1); // remove instance + } + be_pop(vm, 1); // remove method + } + be_pop(vm, 1); // remove instance object + checkBeTop(); + return ret; +} + /*********************************************************************************************\ * VM Observability \*********************************************************************************************/ @@ -336,6 +364,9 @@ void BerryInit(void) { AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_BERRY "Berry initialized, RAM used=%u"), callBerryGC()); berry_init_ok = true; + // Run 'autoconf.preinit()' + callBerryAutoconf("preinit"); + // Run pre-init BrLoad("preinit.be"); // run 'preinit.be' if present } while (0); @@ -759,6 +790,9 @@ bool Xdrv52(uint8_t function) // break; case FUNC_LOOP: if (!berry.autoexec_done) { + // Run 'autoconf.preinit()' + callBerryAutoconf("autoexec"); + BrLoad("autoexec.be"); // run autoexec.be at first tick, so we know all modules are initialized berry.autoexec_done = true; } diff --git a/tasmota/xdrv_54_lvgl.ino b/tasmota/xdrv_54_lvgl.ino index 9d5855099..c8f533310 100644 --- a/tasmota/xdrv_54_lvgl.ino +++ b/tasmota/xdrv_54_lvgl.ino @@ -364,9 +364,6 @@ extern "C" { * display ecosystem. ************************************************************/ -Renderer *Init_uDisplay(const char *desc, int8_t cs); - - void start_lvgl(const char * uconfig); void start_lvgl(const char * uconfig) { @@ -377,7 +374,7 @@ void start_lvgl(const char * uconfig) { if (!renderer || uconfig) { #ifdef USE_UNIVERSAL_DISPLAY // TODO - we will probably support only UNIV_DISPLAY - renderer = Init_uDisplay((char*)uconfig, -1); + renderer = Init_uDisplay((char*)uconfig); if (!renderer) return; #else return; diff --git a/tasmota/xdsp_08_ILI9488_UD.ino b/tasmota/xdsp_08_ILI9488_UD.ino index 8717397d5..712f2fac3 100644 --- a/tasmota/xdsp_08_ILI9488_UD.ino +++ b/tasmota/xdsp_08_ILI9488_UD.ino @@ -26,7 +26,7 @@ bool ili9488_init_done = false; -Renderer *Init_uDisplay(const char *desc, int8_t cs); +Renderer *Init_uDisplay(const char *desc, int8_t cs = -1); void udisp_CheckTouch(void); /*********************************************************************************************/ diff --git a/tasmota/xdsp_17_universal.ino b/tasmota/xdsp_17_universal.ino index d8be8b94b..16a886661 100644 --- a/tasmota/xdsp_17_universal.ino +++ b/tasmota/xdsp_17_universal.ino @@ -433,7 +433,7 @@ bool Xdsp17(uint8_t function) { bool result = false; if (FUNC_DISPLAY_INIT_DRIVER == function) { - Init_uDisplay(0, -1); + Init_uDisplay(nullptr); } else if (udisp_init_done && (XDSP_17 == Settings->display_model)) { switch (function) { From b83d6e9b0402b59f47d9bacd88becc4c2e4bb7a8 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sun, 14 Nov 2021 18:23:08 +0100 Subject: [PATCH 021/185] Avoid bad ffsp pointer if no filesystem --- tasmota/xdrv_50_filesystem.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tasmota/xdrv_50_filesystem.ino b/tasmota/xdrv_50_filesystem.ino index ebd5b681c..8a0ed1d16 100644 --- a/tasmota/xdrv_50_filesystem.ino +++ b/tasmota/xdrv_50_filesystem.ino @@ -102,7 +102,7 @@ void UfsInitOnce(void) { #ifdef ESP8266 ffsp = &LittleFS; if (!LittleFS.begin()) { - ffsp = 0; + ffsp = nullptr; return; } #endif // ESP8266 @@ -114,6 +114,7 @@ void UfsInitOnce(void) { // ffat is second ffsp = &FFat; if (!FFat.begin(true)) { + ffsp = nullptr; return; } ffs_type = UFS_TFAT; From ac2634d8e70c1ed289983d7c08e63a7a1d500285 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sun, 14 Nov 2021 18:32:17 +0100 Subject: [PATCH 022/185] Force Berry and Autoconf to use internal Flash file-system --- lib/libesp32/Berry/default/be_port.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/libesp32/Berry/default/be_port.cpp b/lib/libesp32/Berry/default/be_port.cpp index 1870d3ae3..5da10f47e 100644 --- a/lib/libesp32/Berry/default/be_port.cpp +++ b/lib/libesp32/Berry/default/be_port.cpp @@ -19,8 +19,8 @@ #ifdef USE_UFILESYS #include #include "ZipReadFS.h" - extern FS *ufsp; - FS zip_ufsp(ZipReadFSImplPtr(new ZipReadFSImpl(&ufsp))); + extern FS *ffsp; + FS zip_ufsp(ZipReadFSImplPtr(new ZipReadFSImpl(&ffsp))); #endif // USE_UFILESYS /* this file contains configuration for the file system. */ @@ -105,7 +105,7 @@ extern "C" { const char *path = be_tostring(vm, 1); be_newobject(vm, "list"); - File dir = ufsp->open(path, "r"); + File dir = ffsp->open(path, "r"); if (dir) { dir.rewindDirectory(); while (1) { From ddca584dfeb29212a006917bef67dcd3523ed9fc Mon Sep 17 00:00:00 2001 From: tony-fav <42725386+tony-fav@users.noreply.github.com> Date: Sun, 14 Nov 2021 14:26:00 -0500 Subject: [PATCH 023/185] "details" to "DetailsBLE" for better rule use --- tasmota/xdrv_79_esp32_ble.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_79_esp32_ble.ino b/tasmota/xdrv_79_esp32_ble.ino index 94589f4c4..2dd4b9d40 100644 --- a/tasmota/xdrv_79_esp32_ble.ino +++ b/tasmota/xdrv_79_esp32_ble.ino @@ -1150,7 +1150,7 @@ void setDetails(ble_advertisment_t *ad){ *(p++) = '{'; maxlen--; - strcpy(p, "\"details\":{"); + strcpy(p, "\"DetailsBLE\":{"); int len = strlen(p); p += len; maxlen -= len; From a584d776518cf54d5c0e28895c425e522e3aae99 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sun, 14 Nov 2021 21:38:59 +0100 Subject: [PATCH 024/185] Berry fix unary not --- lib/libesp32/Berry/src/be_code.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/libesp32/Berry/src/be_code.c b/lib/libesp32/Berry/src/be_code.c index b0feff4e1..6a332bb07 100644 --- a/lib/libesp32/Berry/src/be_code.c +++ b/lib/libesp32/Berry/src/be_code.c @@ -569,7 +569,7 @@ static void unaryexp(bfuncinfo *finfo, bopcode op, bexpdesc *e) /* Apply not to conditional expression */ /* If literal compute the value */ /* Or invert t/f subexpressions */ -static void code_not(bexpdesc *e) +static void code_not(bfuncinfo *finfo, bexpdesc *e) { switch (e->type) { case ETINT: e->v.i = e->v.i == 0; break; @@ -578,6 +578,7 @@ static void code_not(bexpdesc *e) case ETBOOL: e->v.i = !e->v.i; break; case ETSTRING: e->v.i = 0; break; default: { + unaryexp(finfo, OP_MOVE, e); int temp = e->t; e->t = e->f; e->f = temp; @@ -620,7 +621,7 @@ int be_code_unop(bfuncinfo *finfo, int op, bexpdesc *e) { switch (op) { case OptNot: - code_not(e); break; + code_not(finfo, e); break; case OptFlip: /* do nothing */ return code_flip(finfo, e); case OptSub: From 48685c2d42f75388e1274cfff54193bb1c3023ca Mon Sep 17 00:00:00 2001 From: stefanbode Date: Sun, 14 Nov 2021 22:17:28 +0100 Subject: [PATCH 025/185] Fixed Tilt Movement + Enhancement PWM Servo Optimized venetian tilt operation when position was not exactly captured during operation. Shutter tried to find correct position and moves up and down because of the tilt. Enhancement to PWM Servos. no minimum movement is required. Every Position can be reached directly --- tasmota/xdrv_27_shutter.ino | 111 ++++++++++++++++++++++-------------- 1 file changed, 68 insertions(+), 43 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 52fba66ff..756f0d544 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -94,11 +94,14 @@ struct SHUTTER { uint16_t close_velocity_max; // maximum of PWM change during closeing. Defines velocity on opening. Steppers and Servos only int32_t accelerator; // speed of ramp-up, ramp down of shutters with velocity control. Steppers and Servos only int8_t tilt_config[5]; // tilt_min, tilt_max, duration, tilt_closed_value, tilt_opened_value - int8_t tilt_real_pos; // -90 to 90 - int16_t tilt_target_pos; - int16_t tilt_start_pos; + int8_t tilt_real_pos; // -90 to 90 + int8_t tilt_target_pos; // target positon for movements of the tilt + int8_t tilt_start_pos; // saved start position before shutter moves uint8_t tilt_velocity; // degree rotation per step 0.05sec - uint16_t venetian_delay = 0; // Delay in steps before venetian shutter start physical moving. Based on tilt position + int8_t tiltmoving; // 0 operating move, 1 = operating tilt + uint16_t venetian_delay = 0; // Delay in steps before venetian shutter start physical moving. Based on tilt position + uint16_t min_realPositionChange = 0; // minimum change of the position before the shutter operates. different for PWM and time based operations + uint16_t min_TiltChange = 0; // minimum change of the tilt before the shutter operates. different for PWM and time based operations } Shutter[MAX_SHUTTERS]; struct SHUTTERGLOBAL { @@ -108,8 +111,7 @@ struct SHUTTERGLOBAL { uint8_t position_mode = 0; // how to calculate actual position: SHT_TIME, SHT_COUNTER, SHT_PWM_VALUE, SHT_PWM_TIME uint8_t skip_relay_change; // avoid overrun at endstops uint8_t start_reported = 0; // indicates of the shutter start was reported through MQTT JSON - uint16_t open_velocity_max = 1000; // maximum of PWM change during opening. Defines velocity on opening. Steppers and Servos only - uint16_t venetian_delay = 0; + uint16_t open_velocity_max = RESOLUTION; // maximum of PWM change during opening. Defines velocity on opening. Steppers and Servos only } ShutterGlobal; #define SHT_DIV_ROUND(__A, __B) (((__A) + (__B)/2) / (__B)) @@ -327,6 +329,10 @@ void ShutterInit(void) Shutter[i].tilt_real_pos = Settings->shutter_tilt_pos[i]; Shutter[i].tilt_velocity = Shutter[i].tilt_config[2] > 0 ? (Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0])/Shutter[i].tilt_config[2] : 1; + Shutter[i].close_velocity_max = ShutterGlobal.open_velocity_max*Shutter[i].open_time / Shutter[i].close_time; + + Shutter[i].min_realPositionChange = 2 * tmax(ShutterGlobal.open_velocity_max, Shutter[i].close_velocity_max); + Shutter[i].min_TiltChange = 2 * Shutter[i].tilt_velocity; switch (ShutterGlobal.position_mode) { case SHT_PWM_VALUE: @@ -334,14 +340,15 @@ void ShutterInit(void) // Initiate pwm range with defaults if not already set. Settings->shutter_pwmrange[0][i] = Settings->shutter_pwmrange[0][i] > 0 ? Settings->shutter_pwmrange[0][i] : pwm_servo_min; Settings->shutter_pwmrange[1][i] = Settings->shutter_pwmrange[1][i] > 0 ? Settings->shutter_pwmrange[1][i] : pwm_servo_max; + Shutter[i].min_realPositionChange = 0; + Shutter[i].min_TiltChange = 0; break; } - Shutter[i].close_velocity_max = ShutterGlobal.open_velocity_max*Shutter[i].open_time / Shutter[i].close_time; - + AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d min realpos_chg: %d, min tilt_chg %d"),i+1,Shutter[i].min_realPositionChange,Shutter[i].min_TiltChange); //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d Openvel %d, Closevel: %d"),i, ShutterGlobal.open_velocity_max, Shutter[i].close_velocity_max); - AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d Init. Pos %d, Inverted %d, Locked %d, End stop time enabled %d, webButtons inverted %d, delay: %d"), + AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d Init. Pos %d, Inv %d, Locked %d, Endstop enab %d, webButt inv %d, Motordel: %d"), i+1, Shutter[i].real_position, - (Settings->shutter_options[i]&1) ? 1 : 0, (Settings->shutter_options[i]&2) ? 1 : 0, (Settings->shutter_options[i]&4) ? 1 : 0, (Settings->shutter_options[i]&8) ? 1 : 0), Shutter[i].motordelay; + (Settings->shutter_options[i]&1) ? 1 : 0, (Settings->shutter_options[i]&2) ? 1 : 0, (Settings->shutter_options[i]&4) ? 1 : 0, (Settings->shutter_options[i]&8) ? 1 : 0, Shutter[i].motordelay); } else { // terminate loop at first INVALID Shutter[i]. @@ -380,7 +387,8 @@ void ShutterReportPosition(bool always, uint32_t index) //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: rules_flag.shutter_moving: %d, moved %d"), TasmotaGlobal.rules_flag.shutter_moving, TasmotaGlobal.rules_flag.shutter_moved); } -void ShutterLimitRealAndTargetPositions(uint32_t i) { +void ShutterLimitRealAndTargetPositions(uint32_t i) +{ if (Shutter[i].real_position<0) Shutter[i].real_position = 0; if (Shutter[i].real_position>Shutter[i].open_max) Shutter[i].real_position = Shutter[i].open_max; if (Shutter[i].target_position<0) Shutter[i].target_position = 0; @@ -461,7 +469,8 @@ void ShutterDecellerateForStop(uint8_t i) } } -void ShutterPowerOff(uint8_t i) { +void ShutterPowerOff(uint8_t i) +{ AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Stop Shutter %d. Switchmode %d"), i+1,Shutter[i].switch_mode); // fix log to indicate correct shutter number ShutterDecellerateForStop(i); switch (Shutter[i].switch_mode) { @@ -490,15 +499,18 @@ void ShutterPowerOff(uint8_t i) { // Store current PWM value to ensure proper position after reboot. switch (ShutterGlobal.position_mode) { case SHT_PWM_VALUE: - char scmnd[20]; -#ifdef SHUTTER_CLEAR_PWM_ONSTOP - // free the PWM servo lock on stop. - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_PWM "%d 0" ), i+1); -#else - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_PWM "%d %d" ), i+1,Shutter[i].pwm_value); -#endif - ExecuteCommand(scmnd, SRC_BUTTON); - break; + Shutter[i].pwm_value = SHT_DIV_ROUND((Settings->shutter_pwmrange[1][i]-Settings->shutter_pwmrange[0][i]) * Shutter[i].target_position , Shutter[i].open_max)+Settings->shutter_pwmrange[0][i]; + analogWrite(Pin(GPIO_PWM1, i), Shutter[i].pwm_value); + AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: PWM final %d"),Shutter[i].pwm_value); + char scmnd[20]; + #ifdef SHUTTER_CLEAR_PWM_ONSTOP + // free the PWM servo lock on stop. + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_PWM "%d 0" ), i+1); + #else + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_PWM "%d %d" ), i+1,Shutter[i].pwm_value); + #endif + //ExecuteCommand(scmnd, SRC_BUTTON); + break; } if (Shutter[i].direction !=0) { Shutter[i].direction = 0; @@ -508,7 +520,6 @@ void ShutterPowerOff(uint8_t i) { void ShutterUpdatePosition(void) { - char scommand[CMDSZ]; char stopic[TOPSZ]; for (uint32_t i = 0; i < TasmotaGlobal.shutters_present; i++) { @@ -518,12 +529,13 @@ void ShutterUpdatePosition(void) XdrvRulesProcess(0); ShutterGlobal.start_reported = 1; } - AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Time %d, cStop %d, cVelo %d, mVelo %d, aVelo %d, mRun %d, aPos %d, aPos2 %d, nStop %d, Trgt %d, mVelo %d, Dir %d, Tilt %d"), + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Time %d, cStop %d, cVelo %d, mVelo %d, aVelo %d, mRun %d, aPos %d, aPos2 %d, nStop %d, Trgt %d, mVelo %d, Dir %d, Tilt %d, TrgtTilt: %d, Tiltmove: %d"), Shutter[i].time, current_stop_way, current_pwm_velocity, velocity_max, Shutter[i].accelerator, min_runtime_ms, current_real_position,Shutter[i].real_position, - next_possible_stop_position, Shutter[i].target_position, velocity_change_per_step_max, Shutter[i].direction,Shutter[i].tilt_real_pos); + next_possible_stop_position, Shutter[i].target_position, velocity_change_per_step_max, Shutter[i].direction,Shutter[i].tilt_real_pos, Shutter[i].tilt_target_pos, + Shutter[i].tiltmoving); - if ( (Shutter[i].real_position * Shutter[i].direction >= Shutter[i].target_position * Shutter[i].direction && - Shutter[i].tilt_real_pos * Shutter[i].direction * Shutter[i].tilt_config[2] >= Shutter[i].tilt_target_pos * Shutter[i].direction * Shutter[i].tilt_config[2]) + if ( ((Shutter[i].real_position * Shutter[i].direction >= Shutter[i].target_position * Shutter[i].direction && Shutter[i].tiltmoving==0) || + ((int16_t)Shutter[i].tilt_real_pos * Shutter[i].direction * Shutter[i].tilt_config[2] >= (int16_t)Shutter[i].tilt_target_pos * Shutter[i].direction * Shutter[i].tilt_config[2] && Shutter[i].tiltmoving==1)) || (ShutterGlobal.position_mode == SHT_COUNTER && Shutter[i].accelerator <0 && Shutter[i].pwm_velocity+Shutter[i].acceleratorshutter_position[i] == 0 ? Shutter[i].tilt_config[0] : Shutter[i].tilt_target_pos; Shutter[i].tilt_target_pos = Settings->shutter_position[i] == 100 ? Shutter[i].tilt_config[1] : Shutter[i].tilt_target_pos; - if (abs(Shutter[i].tilt_real_pos - Shutter[i].tilt_target_pos) > 10) { - AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Tilt does not match akt %d, target %d"),Shutter[i].tilt_real_pos,Shutter[i].tilt_target_pos); + if (abs(Shutter[i].tilt_real_pos - Shutter[i].tilt_target_pos) > Shutter[i].min_TiltChange) { + AddLog(LOG_LEVEL_INFO, PSTR("SHT: Tilt not match %d -> %d"),Shutter[i].tilt_real_pos,Shutter[i].tilt_target_pos); XdrvMailbox.payload = -99; XdrvMailbox.index = i+1; + Shutter[i].tiltmoving = 1; CmndShutterPosition(); return; + } else { + Settings->shutter_tilt_pos[i] = Shutter[i].tilt_real_pos; + Shutter[i].tiltmoving = 0; } ShutterLogPos(i); @@ -558,7 +574,8 @@ void ShutterUpdatePosition(void) } } -bool ShutterState(uint32_t device) { +bool ShutterState(uint32_t device) +{ if (device > 4) { return false; } device--; device &= 3; @@ -583,9 +600,10 @@ void ShutterAllowPreStartProcedure(uint8_t i) void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) { - //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: dir %d, delta1 %d, delta2 %d, grant %d"),direction, (Shutter[i].open_max - Shutter[i].real_position) / Shutter[i].close_velocity, Shutter[i].real_position / Shutter[i].close_velocity, 2+Shutter[i].motordelay); - if ( ( ( (1 == direction) && ((Shutter[i].open_max - Shutter[i].real_position) / 100 <= 2)) - || ( (-1 == direction) && (Shutter[i].real_position / Shutter[i].close_velocity <= 2)) ) && abs(Shutter[i].tilt_real_pos-Shutter[i].tilt_target_pos)/Shutter[i].tilt_velocity <= 2) { + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: dir %d, delta1 %d, delta2 %d"),direction, (Shutter[i].open_max - Shutter[i].real_position) / Shutter[i].close_velocity, Shutter[i].real_position / Shutter[i].close_velocity); + if ( ( ( (1 == direction) && ((Shutter[i].open_max - Shutter[i].real_position) <= Shutter[i].min_realPositionChange)) + || ( (-1 == direction) && (Shutter[i].real_position <= Shutter[i].min_realPositionChange)) ) + && abs(Shutter[i].tilt_real_pos-Shutter[i].tilt_target_pos) <= Shutter[i].min_TiltChange) { ShutterGlobal.skip_relay_change = 1; } else { Shutter[i].pwm_velocity = 0; @@ -614,10 +632,10 @@ void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) Shutter[i].venetian_delay = (Shutter[i].direction > 0 ? Shutter[i].tilt_config[1]-Shutter[i].tilt_real_pos : Shutter[i].tilt_real_pos-Shutter[i].tilt_config[0]) * Shutter[i].tilt_config[2] / (Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0]); //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: real %d, start %d, counter %d,freq_max %d, dir %d, freq %d"),Shutter[i].real_position, Shutter[i].start_position ,RtcSettings.pulse_counter[i],ShutterGlobal.open_velocity_max , Shutter[i].direction ,ShutterGlobal.open_velocity_max ); //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: %d VenetianDelay: %d, Pos: %d, Dir: %d, Delta: %d, Durat: %d, Start: %d, Target: %d"), - //i, Shutter[i].venetian_delay, Shutter[i].tilt_real_pos,Shutter[i].direction,(Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0]), Shutter[i].tilt_config[2],Shutter[i].tilt_start_pos,Shutter[i].tilt_target_pos); + // i, Shutter[i].venetian_delay, Shutter[i].tilt_real_pos,Shutter[i].direction,(Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0]), Shutter[i].tilt_config[2],Shutter[i].tilt_start_pos,Shutter[i].tilt_target_pos); } } - //AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Start shtr%d from %d to %d in direction %d"), i, Shutter[i].start_position, Shutter[i].target_position, Shutter[i].direction); + AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Start shtr%d from %d to %d in direction %d"), i, Shutter[i].start_position, Shutter[i].target_position, Shutter[i].direction); } int32_t ShutterCalculatePosition(uint32_t i) @@ -636,7 +654,7 @@ int32_t ShutterCalculatePosition(uint32_t i) Shutter[i].tilt_real_pos = (Shutter[i].tilt_start_pos + ((Shutter[i].direction * (int16_t)Shutter[i].time * (Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0])) / Shutter[i].tilt_config[2])); } else { Shutter[i].tilt_real_pos = Shutter[i].direction == 1 ? Shutter[i].tilt_config[1] : Shutter[i].tilt_config[0]; - } + } } return Shutter[i].start_position + ( (Shutter[i].time - tmin(Shutter[i].venetian_delay+Shutter[i].motordelay, Shutter[i].time)) * (Shutter[i].direction > 0 ? RESOLUTION : -Shutter[i].close_velocity)); break; @@ -691,6 +709,7 @@ void ShutterRelayChanged(void) case SHT_COUNTER: case SHT_PWM_VALUE: case SHT_PWM_TIME: + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: power off manual change")); ShutterPowerOff(i); switch (powerstate_local) { case 1: @@ -734,7 +753,8 @@ void ShutterRelayChanged(void) } // for (uint32_t i = 0; i < TasmotaGlobal.shutters_present; i++) } -bool ShutterButtonIsSimultaneousHold(uint32_t button_index, uint32_t shutter_index) { +bool ShutterButtonIsSimultaneousHold(uint32_t button_index, uint32_t shutter_index) +{ // check for simultaneous shutter button hold uint32 min_shutterbutton_hold_timer = -1; // -1 == max(uint32) for (uint32_t i = 0; i < MAX_SHUTTER_KEYS; i++) { @@ -1074,7 +1094,6 @@ void CmndShutterIncDec(void) } } - void CmndShutterPosition(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) { @@ -1121,17 +1140,21 @@ void CmndShutterPosition(void) AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: lastsource %d:, real %d, target %d, tiltreal: %d, tilttarget: %d, payload %d"), TasmotaGlobal.last_source, Shutter[index].real_position ,Shutter[index].target_position,Shutter[index].tilt_real_pos, Shutter[index].tilt_target_pos,target_pos_percent); } if ( (target_pos_percent >= 0) && (target_pos_percent <= 100) && - (abs(Shutter[index].target_position - Shutter[index].real_position ) / Shutter[index].close_velocity > 2 || - abs(Shutter[index].tilt_target_pos - Shutter[index].tilt_real_pos ) / Shutter[index].tilt_velocity > 2) ) { + (abs(Shutter[index].target_position - Shutter[index].real_position ) > Shutter[index].min_realPositionChange || + abs(Shutter[index].tilt_target_pos - Shutter[index].tilt_real_pos ) > Shutter[index].min_TiltChange) ) { if (Settings->shutter_options[index] & 4) { if (0 == target_pos_percent) Shutter[index].target_position -= 1 * RESOLUTION * STEPS_PER_SECOND; if (100 == target_pos_percent) Shutter[index].target_position += 1 * RESOLUTION * STEPS_PER_SECOND; } - int8_t new_shutterdirection = Shutter[index].real_position < Shutter[index].target_position ? 1 : -1; - if (Shutter[index].real_position == Shutter[index].target_position) { + int8_t new_shutterdirection; + if (abs(Shutter[index].target_position - Shutter[index].real_position ) > Shutter[index].min_realPositionChange) { + new_shutterdirection = Shutter[index].real_position < Shutter[index].target_position ? 1 : -1; + } else { new_shutterdirection = Shutter[index].tilt_real_pos < Shutter[index].tilt_target_pos ? 1 : -1; } + if (Shutter[index].direction == -new_shutterdirection) { + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Stop shutter to reverse direction")); ShutterPowerOff(index); } if (Shutter[index].direction != new_shutterdirection) { @@ -1203,6 +1226,7 @@ void CmndShutterStopPosition(void) } } } + void CmndShutterOpenTime(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) { @@ -1423,8 +1447,8 @@ void CmndShutterSetHalfway(void) void CmndShutterSetTilt(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) { - if (XdrvMailbox.payload != -99 && XdrvMailbox.payload >= Shutter[XdrvMailbox.index -1].tilt_config[0] && XdrvMailbox.payload <= Shutter[XdrvMailbox.index -1].tilt_config[1] ) { - Shutter[XdrvMailbox.index -1].tilt_target_pos = XdrvMailbox.payload; + if (XdrvMailbox.payload != -99 ) { + Shutter[XdrvMailbox.index -1].tilt_target_pos = tmin(tmax(XdrvMailbox.payload, Shutter[XdrvMailbox.index -1].tilt_config[0]), Shutter[XdrvMailbox.index -1].tilt_config[1]); XdrvMailbox.payload = -99; } if ((XdrvMailbox.data_len > 1) && (XdrvMailbox.payload <= 0)) { @@ -1440,6 +1464,7 @@ void CmndShutterSetTilt(void) } XdrvMailbox.data[0] = '\0'; ResponseCmndNumber(Shutter[XdrvMailbox.index -1].tilt_target_pos); + Shutter[XdrvMailbox.index -1].tiltmoving = 1; CmndShutterPosition(); } From 6da931e4e6c8e43a14cd103b1e0ad2ced222adb8 Mon Sep 17 00:00:00 2001 From: stefanbode Date: Sun, 14 Nov 2021 22:25:03 +0100 Subject: [PATCH 026/185] Update xdrv_27_shutter.ino Missed a change --- tasmota/xdrv_27_shutter.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 756f0d544..de3f20239 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -509,7 +509,7 @@ void ShutterPowerOff(uint8_t i) #else snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_PWM "%d %d" ), i+1,Shutter[i].pwm_value); #endif - //ExecuteCommand(scmnd, SRC_BUTTON); + ExecuteCommand(scmnd, SRC_BUTTON); break; } if (Shutter[i].direction !=0) { From d3ba1dd5fcaaf994cee265ba818d3e2472d16c3f Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Mon, 15 Nov 2021 12:35:48 +0100 Subject: [PATCH 027/185] fix compiler warnings --- .../ESP32-HomeKit/src/esp_hap_char.c | 22 +++++------ .../ESP32-HomeKit/src/esp_hap_ip_services.c | 4 +- .../ESP32-HomeKit/src/esp_hap_main.c | 4 +- .../ESP32-HomeKit/src/esp_hap_serv.c | 6 +-- .../ESP32-HomeKit/src/esp_hap_serv.h | 6 +-- lib/libesp32_div/ESP32-HomeKit/src/hap.h | 38 +++++++++---------- .../ESP32-HomeKit/src/hap_apple_chars.c | 14 +++---- .../ESP32-HomeKit/src/hap_apple_chars.h | 14 +++---- .../ESP32-HomeKit/src/hap_platform_httpd.c | 2 +- lib/libesp32_div/ESP32-HomeKit/src/hexdump.c | 4 +- lib/libesp32_div/ESP32-HomeKit/src/hexdump.h | 2 +- .../ESP32-HomeKit/src/json_generator.c | 36 +++++++++--------- .../ESP32-HomeKit/src/json_generator.h | 26 ++++++------- .../ESP32-HomeKit/src/json_parser.c | 30 +++++++-------- .../ESP32-HomeKit/src/json_parser.h | 24 ++++++------ lib/libesp32_div/ESP32-HomeKit/src/mu_srp.c | 2 +- lib/libesp32_div/ESP32-HomeKit/src/mu_srp.h | 2 +- .../ESP32-HomeKit/src/port/bignum_ESP32.c | 2 +- .../ESP32-HomeKit/src/port/bignum_ESP32.h | 2 +- .../ESP32-HomeKit/src/port/esp_bignum.c | 2 +- lib/libesp32_div/ESP32-HomeKit/src/shatest.c | 6 +-- pio-tools/add_c_flags.py | 4 -- platformio.ini | 1 - 23 files changed, 124 insertions(+), 129 deletions(-) delete mode 100644 pio-tools/add_c_flags.py diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_char.c b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_char.c index 9b712e32e..6b31814af 100644 --- a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_char.c +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_char.c @@ -309,7 +309,7 @@ const hap_val_t *hap_char_get_step_val(hap_char_t *hc) /** * @brief HAP create a characteristics */ -static hap_char_t *hap_char_create(char *type_uuid, uint32_t permission, hap_char_format_t format, hap_val_t val) +static hap_char_t *hap_char_create(const char *type_uuid, uint32_t permission, hap_char_format_t format, hap_val_t val) { __hap_char_t *new_ch; @@ -333,42 +333,42 @@ static hap_char_t *hap_char_create(char *type_uuid, uint32_t permission, hap_cha return (hap_char_t *) new_ch; } -hap_char_t *hap_char_bool_create(char *type_uuid, uint16_t perms, bool b) +hap_char_t *hap_char_bool_create(const char *type_uuid, uint16_t perms, bool b) { hap_val_t val = {.b = b}; return hap_char_create(type_uuid, perms, HAP_CHAR_FORMAT_BOOL, val); } -hap_char_t *hap_char_uint8_create(char *type_uuid, uint16_t perms, uint8_t u8) +hap_char_t *hap_char_uint8_create(const char *type_uuid, uint16_t perms, uint8_t u8) { hap_val_t val = {.u = u8}; return hap_char_create(type_uuid, perms, HAP_CHAR_FORMAT_UINT8, val); } -hap_char_t *hap_char_uint16_create(char *type_uuid, uint16_t perms, uint16_t u16) +hap_char_t *hap_char_uint16_create(const char *type_uuid, uint16_t perms, uint16_t u16) { hap_val_t val = {.u = u16}; return hap_char_create(type_uuid, perms, HAP_CHAR_FORMAT_UINT16, val); } -hap_char_t *hap_char_uint32_create(char *type_uuid, uint16_t perms, uint32_t u32) +hap_char_t *hap_char_uint32_create(const char *type_uuid, uint16_t perms, uint32_t u32) { hap_val_t val = {.u = u32}; return hap_char_create(type_uuid, perms, HAP_CHAR_FORMAT_UINT32, val); } -hap_char_t *hap_char_uint64_create(char *type_uuid, uint16_t perms, uint64_t u64) +hap_char_t *hap_char_uint64_create(const char *type_uuid, uint16_t perms, uint64_t u64) { hap_val_t val = {.i64 = u64}; return hap_char_create(type_uuid, perms, HAP_CHAR_FORMAT_UINT64, val); } -hap_char_t *hap_char_int_create(char *type_uuid, uint16_t perms, int i32) +hap_char_t *hap_char_int_create(const char *type_uuid, uint16_t perms, int i32) { hap_val_t val = {.i = i32}; return hap_char_create(type_uuid, perms, HAP_CHAR_FORMAT_INT, val); } -hap_char_t *hap_char_float_create(char *type_uuid, uint16_t perms, float f) +hap_char_t *hap_char_float_create(const char *type_uuid, uint16_t perms, float f) { hap_val_t val = {.f = f}; return hap_char_create(type_uuid, perms, HAP_CHAR_FORMAT_FLOAT, val); } -hap_char_t *hap_char_string_create(char *type_uuid, uint16_t perms, char *s) +hap_char_t *hap_char_string_create(const char *type_uuid, uint16_t perms, const char *s) { hap_val_t val; if (s) @@ -378,7 +378,7 @@ hap_char_t *hap_char_string_create(char *type_uuid, uint16_t perms, char *s) return hap_char_create(type_uuid, perms, HAP_CHAR_FORMAT_STRING, val); } -hap_char_t *hap_char_data_create(char *type_uuid, uint16_t perms, hap_data_val_t *d) +hap_char_t *hap_char_data_create(const char *type_uuid, uint16_t perms, hap_data_val_t *d) { hap_val_t val = {0}; if (d) { @@ -387,7 +387,7 @@ hap_char_t *hap_char_data_create(char *type_uuid, uint16_t perms, hap_data_val_t return hap_char_create(type_uuid, perms, HAP_CHAR_FORMAT_DATA, val); } -hap_char_t *hap_char_tlv8_create(char *type_uuid, uint16_t perms, hap_tlv8_val_t *t) +hap_char_t *hap_char_tlv8_create(const char *type_uuid, uint16_t perms, hap_tlv8_val_t *t) { hap_val_t val = {0}; if (t) { diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_ip_services.c b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_ip_services.c index 4f5031a64..357db53d7 100644 --- a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_ip_services.c +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_ip_services.c @@ -234,7 +234,7 @@ static struct httpd_uri hap_pair_verify = { .handler = hap_http_pair_verify_handler, }; -static int hap_add_char_val_json(hap_char_format_t format, char *key, +static int hap_add_char_val_json(hap_char_format_t format, const char *key, hap_val_t *val, json_gen_str_t *jptr) { switch (format) { @@ -970,7 +970,7 @@ static int hap_http_put_characteristics(httpd_req_t *req) return HAP_SUCCESS; } -static bool hap_get_bool_url_param(char *query_str, char *key) +static bool hap_get_bool_url_param(const char *query_str, const char *key) { char val[6]; /* Max string will be "false" */ if (httpd_query_key_value(query_str, key, val, sizeof(val)) == HAP_SUCCESS) { diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_main.c b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_main.c index 459b6a0ed..6fe937692 100644 --- a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_main.c +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_main.c @@ -81,7 +81,7 @@ static void hap_nw_configured_sm(hap_internal_event_t event, hap_state_t *state) static void hap_common_sm(hap_internal_event_t event) { - char *reboot_reason = HAP_REBOOT_REASON_UNKNOWN; + const char *reboot_reason = HAP_REBOOT_REASON_UNKNOWN; switch (event) { case HAP_INTERNAL_EVENT_RESET_PAIRINGS: ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Resetting all Pairing Information"); @@ -149,7 +149,7 @@ static void hap_common_sm(hap_internal_event_t event) /* Wait for some time after peeforming the operations and then reboot */ ESP_MFI_DEBUG(ESP_MFI_DEBUG_INFO, "Rebooting..."); - hap_report_event(HAP_EVENT_ACC_REBOOTING, reboot_reason, strlen(reboot_reason) + 1); + hap_report_event(HAP_EVENT_ACC_REBOOTING, (void*)reboot_reason, strlen(reboot_reason) + 1); vTaskDelay(1000 / hap_platform_os_get_msec_per_tick()); esp_restart(); } diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_serv.c b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_serv.c index 8c8bd9f25..0ab11ca41 100644 --- a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_serv.c +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_serv.c @@ -110,7 +110,7 @@ hap_char_t *hap_serv_get_char_by_uuid(hap_serv_t *hs, const char *uuid) /** * @brief get characteristics UUID prefix number */ - char *hap_serv_get_uuid(hap_serv_t *hs) + const char *hap_serv_get_uuid(hap_serv_t *hs) { return ((__hap_serv_t *)hs)->type_uuid; } @@ -145,7 +145,7 @@ static int hap_serv_def_bulk_read_cb(hap_read_data_t read_data[], int count, /** * @brief HAP create a service */ -hap_serv_t *hap_serv_create(char *type_uuid) +hap_serv_t *hap_serv_create(const char *type_uuid) { ESP_MFI_ASSERT(type_uuid); __hap_serv_t *_hs = hap_platform_memory_calloc(1, sizeof(__hap_serv_t)); @@ -198,7 +198,7 @@ uint32_t hap_serv_get_iid(hap_serv_t *hs) return tmp->iid; } -char *hap_serv_get_type_uuid(hap_serv_t *hs) +const char *hap_serv_get_type_uuid(hap_serv_t *hs) { if (!hs) return 0; diff --git a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_serv.h b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_serv.h index 8d041d85f..f3545db7a 100644 --- a/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_serv.h +++ b/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_serv.h @@ -44,7 +44,7 @@ typedef struct hap_linked_serv hap_linked_serv_t; * HAP service information */ typedef struct { - char *type_uuid; /* String that defines the type of the service. */ + const char *type_uuid; /* String that defines the type of the service. */ uint32_t iid; /* service instance ID */ @@ -69,8 +69,8 @@ typedef struct { bool hap_serv_get_hidden(hap_serv_t *hs); bool hap_serv_get_primary(hap_serv_t *hs); hap_char_t *hap_serv_get_char_by_iid(hap_serv_t *hs, int32_t iid); - char *hap_serv_get_uuid(hap_serv_t *hs); -hap_serv_t *hap_serv_create(char *type_uuid); +const char *hap_serv_get_uuid(hap_serv_t *hs); +hap_serv_t *hap_serv_create(const char *type_uuid); void hap_serv_delete(hap_serv_t *hs); int hap_serv_add_char(hap_serv_t *hs, hap_char_t *hc); #ifdef __cplusplus diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hap.h b/lib/libesp32_div/ESP32-HomeKit/src/hap.h index fdd80f528..1eb9f59a7 100755 --- a/lib/libesp32_div/ESP32-HomeKit/src/hap.h +++ b/lib/libesp32_div/ESP32-HomeKit/src/hap.h @@ -234,23 +234,23 @@ typedef int (*hap_identify_routine_t) (hap_acc_t *acc); /** HAP Accessory configuration */ typedef struct { /** Name (Mandatory) */ - char *name; + const char *name; /** Model (Mandatory) */ - char *model; + const char *model; /** Manufacturer (Mandatory) */ - char *manufacturer; + const char *manufacturer; /** Serial Number (Mandatory) */ - char *serial_num; + const char *serial_num; /** Firmware Revision number in format x[.y[.z]] (Mandatory) */ - char *fw_rev; + const char *fw_rev; /** Hardware revision number in format x[.y[.z]] (Optional. Can be NULL )*/ - char *hw_rev; + const char *hw_rev; /** HAP Protocol version supported by the accessory. Should be set to "1.1" * @note The value set here will currently be ignored and assumed to be 1.1 * as it is the only protocol version currently supported. * This is valid only for the Primary accessory. */ - char *pv; + const char *pv; /** Category Identifier for the Accessory. This is valid only for the * primary accessory */ @@ -640,7 +640,7 @@ hap_serv_t *hap_acc_get_first_serv(hap_acc_t *ha); * @return Handle for the characteristic object created * @return NULL on error */ -hap_char_t *hap_char_bool_create(char *type_uuid, uint16_t perms, bool val); +hap_char_t *hap_char_bool_create(const char *type_uuid, uint16_t perms, bool val); /** * @brief Create an 8-bit unsigned integer Characteristic Object @@ -652,7 +652,7 @@ hap_char_t *hap_char_bool_create(char *type_uuid, uint16_t perms, bool val); * @return Handle for the characteristic object created * @return NULL on error */ -hap_char_t *hap_char_uint8_create(char *type_uuid, uint16_t perms, uint8_t val); +hap_char_t *hap_char_uint8_create(const char *type_uuid, uint16_t perms, uint8_t val); /** * @brief Create a 16-bit unsigned integer Characteristic Object @@ -664,7 +664,7 @@ hap_char_t *hap_char_uint8_create(char *type_uuid, uint16_t perms, uint8_t val); * @return Handle for the characteristic object created * @return NULL on error */ -hap_char_t *hap_char_uint16_create(char *type_uuid, uint16_t perms, uint16_t val); +hap_char_t *hap_char_uint16_create(const char *type_uuid, uint16_t perms, uint16_t val); /** * @brief Create a 32-bit unsigned integer Characteristic Object @@ -676,7 +676,7 @@ hap_char_t *hap_char_uint16_create(char *type_uuid, uint16_t perms, uint16_t val * @return Handle for the characteristic object created * @return NULL on error */ -hap_char_t *hap_char_uint32_create(char *type_uuid, uint16_t perms, uint32_t val); +hap_char_t *hap_char_uint32_create(const char *type_uuid, uint16_t perms, uint32_t val); /** * @brief Create a 64-bit unsigned integer Characteristic Object @@ -688,7 +688,7 @@ hap_char_t *hap_char_uint32_create(char *type_uuid, uint16_t perms, uint32_t val * @return Handle for the characteristic object created * @return NULL on error */ -hap_char_t *hap_char_uint64_create(char *type_uuid, uint16_t perms, uint64_t val); +hap_char_t *hap_char_uint64_create(const char *type_uuid, uint16_t perms, uint64_t val); /** * @brief Create a 32-bit signed integer Characteristic Object @@ -700,7 +700,7 @@ hap_char_t *hap_char_uint64_create(char *type_uuid, uint16_t perms, uint64_t val * @return Handle for the characteristic object created * @return NULL on error */ -hap_char_t *hap_char_int_create(char *type_uuid, uint16_t perms, int val); +hap_char_t *hap_char_int_create(const char *type_uuid, uint16_t perms, int val); /** * @brief Create a Floating point Characteristic Object @@ -712,7 +712,7 @@ hap_char_t *hap_char_int_create(char *type_uuid, uint16_t perms, int val); * @return Handle for the characteristic object created * @return NULL on error */ -hap_char_t *hap_char_float_create(char *type_uuid, uint16_t perms, float val); +hap_char_t *hap_char_float_create(const char *type_uuid, uint16_t perms, float val); /** * @brief Create a String Characteristic Object @@ -724,7 +724,7 @@ hap_char_t *hap_char_float_create(char *type_uuid, uint16_t perms, float val); * @return Handle for the characteristic object created * @return NULL on error */ -hap_char_t *hap_char_string_create(char *type_uuid, uint16_t perms, char *val); +hap_char_t *hap_char_string_create(const char *type_uuid, uint16_t perms, const char *val); /** * @brief Create a Data Characteristic Object @@ -736,7 +736,7 @@ hap_char_t *hap_char_string_create(char *type_uuid, uint16_t perms, char *val); * @return Handle for the characteristic object created * @return NULL on error */ -hap_char_t *hap_char_data_create(char *type_uuid, uint16_t perms, hap_data_val_t *val); +hap_char_t *hap_char_data_create(const char *type_uuid, uint16_t perms, hap_data_val_t *val); /** * @brief Create a TLV8 Characteristic Object @@ -748,7 +748,7 @@ hap_char_t *hap_char_data_create(char *type_uuid, uint16_t perms, hap_data_val_t * @return Handle for the characteristic object created * @return NULL on error */ -hap_char_t *hap_char_tlv8_create(char *type_uuid, uint16_t perms, hap_tlv8_val_t *val); +hap_char_t *hap_char_tlv8_create(const char *type_uuid, uint16_t perms, hap_tlv8_val_t *val); /** * @brief Delete a characteristic object @@ -765,7 +765,7 @@ void hap_char_delete(hap_char_t *hc); * @return Handle for the service object created * @return NULL on error */ -hap_serv_t *hap_serv_create(char *type_uuid); +hap_serv_t *hap_serv_create(const char *type_uuid); /** * @brief Delete a service object @@ -884,7 +884,7 @@ uint32_t hap_serv_get_iid(hap_serv_t *hs); * * @return Type UUID for the service */ -char *hap_serv_get_type_uuid(hap_serv_t *hs); +const char *hap_serv_get_type_uuid(hap_serv_t *hs); /** * @brief Get parent Service for given Characteristic * diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hap_apple_chars.c b/lib/libesp32_div/ESP32-HomeKit/src/hap_apple_chars.c index de079b4dd..0b811e3c9 100755 --- a/lib/libesp32_div/ESP32-HomeKit/src/hap_apple_chars.c +++ b/lib/libesp32_div/ESP32-HomeKit/src/hap_apple_chars.c @@ -128,7 +128,7 @@ hap_char_t *hap_char_current_temperature_create(float curr_temp) } /* Char: Firmware Revision */ -hap_char_t *hap_char_firmware_revision_create(char *fw_rev) +hap_char_t *hap_char_firmware_revision_create(const char *fw_rev) { hap_char_t *hc = hap_char_string_create(HAP_CHAR_UUID_FIRMWARE_REVISION, HAP_CHAR_PERM_PR, fw_rev); @@ -139,7 +139,7 @@ hap_char_t *hap_char_firmware_revision_create(char *fw_rev) } /* Char: Hardware Revision */ -hap_char_t *hap_char_hardware_revision_create(char *hw_rev) +hap_char_t *hap_char_hardware_revision_create(const char *hw_rev) { hap_char_t *hc = hap_char_string_create(HAP_CHAR_UUID_HARDWARE_REVISION, HAP_CHAR_PERM_PR, hw_rev); @@ -218,7 +218,7 @@ hap_char_t *hap_char_lock_target_state_create(uint8_t lock_targ_state) } /* Char: Manufacturer */ -hap_char_t *hap_char_manufacturer_create(char *manufacturer) +hap_char_t *hap_char_manufacturer_create(const char *manufacturer) { hap_char_t *hc = hap_char_string_create(HAP_CHAR_UUID_MANUFACTURER, HAP_CHAR_PERM_PR, manufacturer); @@ -229,7 +229,7 @@ hap_char_t *hap_char_manufacturer_create(char *manufacturer) } /* Char: Model */ -hap_char_t *hap_char_model_create(char *model) +hap_char_t *hap_char_model_create(const char *model) { hap_char_t *hc = hap_char_string_create(HAP_CHAR_UUID_MODEL, HAP_CHAR_PERM_PR, model); @@ -252,7 +252,7 @@ hap_char_t *hap_char_motion_detected_create(bool motion_detected) } /* Char: Name */ -hap_char_t *hap_char_name_create(char *name) +hap_char_t *hap_char_name_create(const char *name) { hap_char_t *hc = hap_char_string_create(HAP_CHAR_UUID_NAME, HAP_CHAR_PERM_PR, name); @@ -341,7 +341,7 @@ hap_char_t *hap_char_saturation_create(float saturation) } /* Char: Serial Number */ -hap_char_t *hap_char_serial_number_create(char *serial_num) +hap_char_t *hap_char_serial_number_create(const char *serial_num) { hap_char_t *hc = hap_char_string_create(HAP_CHAR_UUID_SERIAL_NUMBER, HAP_CHAR_PERM_PR, serial_num); @@ -424,7 +424,7 @@ hap_char_t *hap_char_temperature_display_units_create(uint8_t temp_disp_units) } /* Char: Version */ -hap_char_t *hap_char_version_create(char *version) +hap_char_t *hap_char_version_create(const char *version) { hap_char_t *hc = hap_char_string_create(HAP_CHAR_UUID_VERSION, HAP_CHAR_PERM_PR, version); diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hap_apple_chars.h b/lib/libesp32_div/ESP32-HomeKit/src/hap_apple_chars.h index 90aa12e08..6fcc69697 100755 --- a/lib/libesp32_div/ESP32-HomeKit/src/hap_apple_chars.h +++ b/lib/libesp32_div/ESP32-HomeKit/src/hap_apple_chars.h @@ -227,7 +227,7 @@ hap_char_t *hap_char_current_temperature_create(float curr_temp); * @return Pointer to the characteristic object on success * @return NULL on failure */ -hap_char_t *hap_char_firmware_revision_create(char *fw_rev); +hap_char_t *hap_char_firmware_revision_create(const char *fw_rev); /** Create Hardware Revision Characteristic * @@ -239,7 +239,7 @@ hap_char_t *hap_char_firmware_revision_create(char *fw_rev); * @return Pointer to the characteristic object on success * @return NULL on failure */ -hap_char_t *hap_char_hardware_revision_create(char *hw_rev); +hap_char_t *hap_char_hardware_revision_create(const char *hw_rev); /** Heating Threshold Temperature Characteristic * @@ -309,7 +309,7 @@ hap_char_t *hap_char_lock_target_state_create(uint8_t lock_targ_state); * @return Pointer to the characteristic object on success * @return NULL on failure */ -hap_char_t *hap_char_manufacturer_create(char *manufacturer); +hap_char_t *hap_char_manufacturer_create(const char *manufacturer); /** Create Model Characteristic * @@ -321,7 +321,7 @@ hap_char_t *hap_char_manufacturer_create(char *manufacturer); * @return Pointer to the characteristic object on success * @return NULL on failure */ -hap_char_t *hap_char_model_create(char *model); +hap_char_t *hap_char_model_create(const char *model); /** Create Motion Detected Characteristic * @@ -345,7 +345,7 @@ hap_char_t *hap_char_motion_detected_create(bool motion_detected); * @return Pointer to the characteristic object on success * @return NULL on failure */ -hap_char_t *hap_char_name_create(char *name); +hap_char_t *hap_char_name_create(const char *name); /** Create Obstruction Detected Characteristic * @@ -429,7 +429,7 @@ hap_char_t *hap_char_saturation_create(float saturation); * @return Pointer to the characteristic object on success * @return NULL on failure */ -hap_char_t *hap_char_serial_number_create(char *serial_num); +hap_char_t *hap_char_serial_number_create(const char *serial_num); /** Create Target Door State Characteristic * @@ -501,7 +501,7 @@ hap_char_t *hap_char_temperature_display_units_create(uint8_t temp_disp_units); * @return Pointer to the characteristic object on success * @return NULL on failure */ -hap_char_t *hap_char_version_create(char *version); +hap_char_t *hap_char_version_create(const char *version); /** Create Security System Current State Characteristic * diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_httpd.c b/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_httpd.c index 9bd679da4..7d19b62e8 100644 --- a/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_httpd.c +++ b/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_httpd.c @@ -82,7 +82,7 @@ esp_err_t hap_platform_httpd_set_sess_ctx(httpd_req_t *req, void *ctx, httpd_fre return ESP_FAIL; } -static char * hap_platform_httpd_rqtype_to_string(int method) +static const char * hap_platform_httpd_rqtype_to_string(int method) { switch (method) { case HTTP_GET: diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hexdump.c b/lib/libesp32_div/ESP32-HomeKit/src/hexdump.c index f6e7e0aef..dfa3a56fe 100644 --- a/lib/libesp32_div/ESP32-HomeKit/src/hexdump.c +++ b/lib/libesp32_div/ESP32-HomeKit/src/hexdump.c @@ -16,7 +16,7 @@ //#define HEX_DBG_ENABLE #ifdef HEX_DBG_ENABLE -void hex_dbg_with_name(char *name, unsigned char *buf, int buf_len) +void hex_dbg_with_name(const char *name, unsigned char *buf, int buf_len) { int i; printf("%s: ", name); @@ -28,7 +28,7 @@ void hex_dbg_with_name(char *name, unsigned char *buf, int buf_len) printf("\r\n"); } #else -void hex_dbg_with_name(char *name, unsigned char *buf, int buf_len) +void hex_dbg_with_name(const char *name, unsigned char *buf, int buf_len) { } #endif /* HEX_DBG_ENABLED */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hexdump.h b/lib/libesp32_div/ESP32-HomeKit/src/hexdump.h index a64bc7c18..e6b0009e5 100644 --- a/lib/libesp32_div/ESP32-HomeKit/src/hexdump.h +++ b/lib/libesp32_div/ESP32-HomeKit/src/hexdump.h @@ -13,6 +13,6 @@ // limitations under the License. #ifndef _HEXDUMP_H_ #define _HEXDUMP_H_ -void hex_dbg_with_name(char *name, unsigned char *buf, int buf_len); +void hex_dbg_with_name(const char *name, unsigned char *buf, int buf_len); #endif /* _HEXDUMP_H_ */ diff --git a/lib/libesp32_div/ESP32-HomeKit/src/json_generator.c b/lib/libesp32_div/ESP32-HomeKit/src/json_generator.c index 947fb62b5..61102f92f 100644 --- a/lib/libesp32_div/ESP32-HomeKit/src/json_generator.c +++ b/lib/libesp32_div/ESP32-HomeKit/src/json_generator.c @@ -34,13 +34,13 @@ static inline int json_gen_get_empty_len(json_gen_str_t *jstr) * flushed out will always be equal to the size of the buffer unless * this is the last chunk being flushed out on json_gen_end_str() */ -static int json_gen_add_to_str(json_gen_str_t *jstr, char *str) +static int json_gen_add_to_str(json_gen_str_t *jstr, const char *str) { if (!str) { return 0; } int len = strlen(str); - char *cur_ptr = str; + const char *cur_ptr = str; while (1) { int len_remaining = json_gen_get_empty_len(jstr); int copy_len = len_remaining > len ? len : len_remaining; @@ -91,7 +91,7 @@ static inline void json_gen_handle_comma(json_gen_str_t *jstr) } -static int json_gen_handle_name(json_gen_str_t *jstr, char *name) +static int json_gen_handle_name(json_gen_str_t *jstr, const char *name) { json_gen_add_to_str(jstr, "\""); json_gen_add_to_str(jstr, name); @@ -126,7 +126,7 @@ int json_gen_end_array(json_gen_str_t *jstr) return json_gen_add_to_str(jstr, "]"); } -int json_gen_push_object(json_gen_str_t *jstr, char *name) +int json_gen_push_object(json_gen_str_t *jstr, const char *name) { json_gen_handle_comma(jstr); json_gen_handle_name(jstr, name); @@ -140,7 +140,7 @@ int json_gen_pop_object(json_gen_str_t *jstr) return json_gen_add_to_str(jstr, "}"); } -int json_gen_push_object_str(json_gen_str_t *jstr, char *name, char *object_str) +int json_gen_push_object_str(json_gen_str_t *jstr, const char *name, char *object_str) { json_gen_handle_comma(jstr); json_gen_handle_name(jstr, name); @@ -148,7 +148,7 @@ int json_gen_push_object_str(json_gen_str_t *jstr, char *name, char *object_str) return json_gen_add_to_str(jstr, object_str); } -int json_gen_push_array(json_gen_str_t *jstr, char *name) +int json_gen_push_array(json_gen_str_t *jstr, const char *name) { json_gen_handle_comma(jstr); json_gen_handle_name(jstr, name); @@ -161,7 +161,7 @@ int json_gen_pop_array(json_gen_str_t *jstr) return json_gen_add_to_str(jstr, "]"); } -int json_gen_push_array_str(json_gen_str_t *jstr, char *name, char *array_str) +int json_gen_push_array_str(json_gen_str_t *jstr, const char *name, char *array_str) { json_gen_handle_comma(jstr); json_gen_handle_name(jstr, name); @@ -177,7 +177,7 @@ static int json_gen_set_bool(json_gen_str_t *jstr, bool val) else return json_gen_add_to_str(jstr, "false"); } -int json_gen_obj_set_bool(json_gen_str_t *jstr, char *name, bool val) +int json_gen_obj_set_bool(json_gen_str_t *jstr, const char *name, bool val) { json_gen_handle_comma(jstr); json_gen_handle_name(jstr, name); @@ -198,7 +198,7 @@ static int json_gen_set_int(json_gen_str_t *jstr, int val) return json_gen_add_to_str(jstr, str); } -int json_gen_obj_set_int(json_gen_str_t *jstr, char *name, int val) +int json_gen_obj_set_int(json_gen_str_t *jstr, const char *name, int val) { json_gen_handle_comma(jstr); json_gen_handle_name(jstr, name); @@ -219,7 +219,7 @@ static int json_gen_set_float(json_gen_str_t *jstr, float val) snprintf(str, MAX_FLOAT_IN_STR, "%.*f", JSON_FLOAT_PRECISION, val); return json_gen_add_to_str(jstr, str); } -int json_gen_obj_set_float(json_gen_str_t *jstr, char *name, float val) +int json_gen_obj_set_float(json_gen_str_t *jstr, const char *name, float val) { json_gen_handle_comma(jstr); json_gen_handle_name(jstr, name); @@ -231,7 +231,7 @@ int json_gen_arr_set_float(json_gen_str_t *jstr, float val) return json_gen_set_float(jstr, val); } -static int json_gen_set_string(json_gen_str_t *jstr, char *val) +static int json_gen_set_string(json_gen_str_t *jstr, const char *val) { jstr->comma_req = true; json_gen_add_to_str(jstr, "\""); @@ -239,40 +239,40 @@ static int json_gen_set_string(json_gen_str_t *jstr, char *val) return json_gen_add_to_str(jstr, "\""); } -int json_gen_obj_set_string(json_gen_str_t *jstr, char *name, char *val) +int json_gen_obj_set_string(json_gen_str_t *jstr, const char *name, const char *val) { json_gen_handle_comma(jstr); json_gen_handle_name(jstr, name); return json_gen_set_string(jstr, val); } -int json_gen_arr_set_string(json_gen_str_t *jstr, char *val) +int json_gen_arr_set_string(json_gen_str_t *jstr, const char *val) { json_gen_handle_comma(jstr); return json_gen_set_string(jstr, val); } -static int json_gen_set_long_string(json_gen_str_t *jstr, char *val) +static int json_gen_set_long_string(json_gen_str_t *jstr, const char *val) { jstr->comma_req = true; json_gen_add_to_str(jstr, "\""); return json_gen_add_to_str(jstr, val); } -int json_gen_obj_start_long_string(json_gen_str_t *jstr, char *name, char *val) +int json_gen_obj_start_long_string(json_gen_str_t *jstr, const char *name, const char *val) { json_gen_handle_comma(jstr); json_gen_handle_name(jstr, name); return json_gen_set_long_string(jstr, val); } -int json_gen_arr_start_long_string(json_gen_str_t *jstr, char *val) +int json_gen_arr_start_long_string(json_gen_str_t *jstr, const char *val) { json_gen_handle_comma(jstr); return json_gen_set_long_string(jstr, val); } -int json_gen_add_to_long_string(json_gen_str_t *jstr, char *val) +int json_gen_add_to_long_string(json_gen_str_t *jstr, const char *val) { return json_gen_add_to_str(jstr, val); } @@ -286,7 +286,7 @@ static int json_gen_set_null(json_gen_str_t *jstr) jstr->comma_req = true; return json_gen_add_to_str(jstr, "null"); } -int json_gen_obj_set_null(json_gen_str_t *jstr, char *name) +int json_gen_obj_set_null(json_gen_str_t *jstr, const char *name) { json_gen_handle_comma(jstr); json_gen_handle_name(jstr, name); diff --git a/lib/libesp32_div/ESP32-HomeKit/src/json_generator.h b/lib/libesp32_div/ESP32-HomeKit/src/json_generator.h index 540e12461..b4cf4be11 100644 --- a/lib/libesp32_div/ESP32-HomeKit/src/json_generator.h +++ b/lib/libesp32_div/ESP32-HomeKit/src/json_generator.h @@ -170,7 +170,7 @@ int json_gen_end_array(json_gen_str_t *jstr); * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data * added after that */ -int json_gen_push_object(json_gen_str_t *jstr, char *name); +int json_gen_push_object(json_gen_str_t *jstr, const char *name); /** Pop a named JSON object * @@ -204,7 +204,7 @@ int json_gen_pop_object(json_gen_str_t *jstr); * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data * added after that. */ -int json_gen_push_object_str(json_gen_str_t *jstr, char *name, char *object_str); +int json_gen_push_object_str(json_gen_str_t *jstr, const char *name, char *object_str); /** Push a named JSON array * @@ -219,7 +219,7 @@ int json_gen_push_object_str(json_gen_str_t *jstr, char *name, char *object_str) * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data * added after that */ -int json_gen_push_array(json_gen_str_t *jstr, char *name); +int json_gen_push_array(json_gen_str_t *jstr, const char *name); /** Pop a named JSON array * @@ -253,7 +253,7 @@ int json_gen_pop_array(json_gen_str_t *jstr); * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data * added after that. */ -int json_gen_push_array_str(json_gen_str_t *jstr, char *name, char *array_str); +int json_gen_push_array_str(json_gen_str_t *jstr, const char *name, char *array_str); /** Add a boolean element to an object * @@ -272,7 +272,7 @@ int json_gen_push_array_str(json_gen_str_t *jstr, char *name, char *array_str); * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data * added after that */ -int json_gen_obj_set_bool(json_gen_str_t *jstr, char *name, bool val); +int json_gen_obj_set_bool(json_gen_str_t *jstr, const char *name, bool val); /** Add an integer element to an object * @@ -291,7 +291,7 @@ int json_gen_obj_set_bool(json_gen_str_t *jstr, char *name, bool val); * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data * added after that */ -int json_gen_obj_set_int(json_gen_str_t *jstr, char *name, int val); +int json_gen_obj_set_int(json_gen_str_t *jstr, const char *name, int val); /** Add a float element to an object * @@ -310,7 +310,7 @@ int json_gen_obj_set_int(json_gen_str_t *jstr, char *name, int val); * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data * added after that */ -int json_gen_obj_set_float(json_gen_str_t *jstr, char *name, float val); +int json_gen_obj_set_float(json_gen_str_t *jstr, const char *name, float val); /** Add a string element to an object * @@ -329,7 +329,7 @@ int json_gen_obj_set_float(json_gen_str_t *jstr, char *name, float val); * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data * added after that */ -int json_gen_obj_set_string(json_gen_str_t *jstr, char *name, char *val); +int json_gen_obj_set_string(json_gen_str_t *jstr, const char *name, const char *val); /** Add a NULL element to an object * @@ -347,7 +347,7 @@ int json_gen_obj_set_string(json_gen_str_t *jstr, char *name, char *val); * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data * added after that */ -int json_gen_obj_set_null(json_gen_str_t *jstr, char *name); +int json_gen_obj_set_null(json_gen_str_t *jstr, const char *name); /** Add a boolean element to an array * @@ -411,7 +411,7 @@ int json_gen_arr_set_float(json_gen_str_t *jstr, float val); * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data * added after that */ -int json_gen_arr_set_string(json_gen_str_t *jstr, char *val); +int json_gen_arr_set_string(json_gen_str_t *jstr, const char *val); /** Add a NULL element to an array * @@ -448,7 +448,7 @@ int json_gen_arr_set_null(json_gen_str_t *jstr); * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data * added after that */ -int json_gen_obj_start_long_string(json_gen_str_t *jstr, char *name, char *val); +int json_gen_obj_start_long_string(json_gen_str_t *jstr, const char *name, const char *val); /** Start a Long string in an array * @@ -469,7 +469,7 @@ int json_gen_obj_start_long_string(json_gen_str_t *jstr, char *name, char *val); * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data * added after that */ -int json_gen_arr_start_long_string(json_gen_str_t *jstr, char *val); +int json_gen_arr_start_long_string(json_gen_str_t *jstr, const char *val); /** Add to a JSON Long string * @@ -485,7 +485,7 @@ int json_gen_arr_start_long_string(json_gen_str_t *jstr, char *val); * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data * added after that */ -int json_gen_add_to_long_string(json_gen_str_t *jstr, char *val); +int json_gen_add_to_long_string(json_gen_str_t *jstr, const char *val); /** End a JSON Long string * diff --git a/lib/libesp32_div/ESP32-HomeKit/src/json_parser.c b/lib/libesp32_div/ESP32-HomeKit/src/json_parser.c index 65a915591..e6c47fb68 100644 --- a/lib/libesp32_div/ESP32-HomeKit/src/json_parser.c +++ b/lib/libesp32_div/ESP32-HomeKit/src/json_parser.c @@ -23,7 +23,7 @@ #include #include -static bool token_matches_str(jparse_ctx_t *ctx, json_tok_t *tok, char *str) +static bool token_matches_str(jparse_ctx_t *ctx, json_tok_t *tok, const char *str) { char *js = ctx->js; return ((strncmp(js + tok->start, str, strlen(str)) == 0) @@ -100,7 +100,7 @@ static int json_tok_to_string(jparse_ctx_t *jctx, json_tok_t *tok, char *val, in return OS_SUCCESS; } -static json_tok_t *json_obj_search(jparse_ctx_t *jctx, char *key) +static json_tok_t *json_obj_search(jparse_ctx_t *jctx, const char *key) { json_tok_t *tok = jctx->cur; int size = tok->size; @@ -118,7 +118,7 @@ static json_tok_t *json_obj_search(jparse_ctx_t *jctx, char *key) return NULL; } -static json_tok_t *json_obj_get_val_tok(jparse_ctx_t *jctx, char *name, jsmntype_t type) +static json_tok_t *json_obj_get_val_tok(jparse_ctx_t *jctx, const char *name, jsmntype_t type) { json_tok_t *tok = json_obj_search(jctx, name); if (!tok) @@ -129,7 +129,7 @@ static json_tok_t *json_obj_get_val_tok(jparse_ctx_t *jctx, char *name, jsmntype return tok; } -int json_obj_get_array(jparse_ctx_t *jctx, char *name, int *num_elem) +int json_obj_get_array(jparse_ctx_t *jctx, const char *name, int *num_elem) { json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_ARRAY); if (!tok) @@ -153,7 +153,7 @@ int json_obj_leave_array(jparse_ctx_t *jctx) return OS_SUCCESS; } -int json_obj_get_object(jparse_ctx_t *jctx, char *name) +int json_obj_get_object(jparse_ctx_t *jctx, const char *name) { json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_OBJECT); if (!tok) @@ -176,7 +176,7 @@ int json_obj_leave_object(jparse_ctx_t *jctx) return OS_SUCCESS; } -int json_obj_get_bool(jparse_ctx_t *jctx, char *name, bool *val) +int json_obj_get_bool(jparse_ctx_t *jctx, const char *name, bool *val) { json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_PRIMITIVE); if (!tok) @@ -184,7 +184,7 @@ int json_obj_get_bool(jparse_ctx_t *jctx, char *name, bool *val) return json_tok_to_bool(jctx, tok, val); } -int json_obj_get_int(jparse_ctx_t *jctx, char *name, int *val) +int json_obj_get_int(jparse_ctx_t *jctx, const char *name, int *val) { json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_PRIMITIVE); if (!tok) @@ -192,7 +192,7 @@ int json_obj_get_int(jparse_ctx_t *jctx, char *name, int *val) return json_tok_to_int(jctx, tok, val); } -int json_obj_get_int64(jparse_ctx_t *jctx, char *name, int64_t *val) +int json_obj_get_int64(jparse_ctx_t *jctx, const char *name, int64_t *val) { json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_PRIMITIVE); if (!tok) @@ -200,7 +200,7 @@ int json_obj_get_int64(jparse_ctx_t *jctx, char *name, int64_t *val) return json_tok_to_int64(jctx, tok, val); } -int json_obj_get_float(jparse_ctx_t *jctx, char *name, float *val) +int json_obj_get_float(jparse_ctx_t *jctx, const char *name, float *val) { json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_PRIMITIVE); if (!tok) @@ -208,7 +208,7 @@ int json_obj_get_float(jparse_ctx_t *jctx, char *name, float *val) return json_tok_to_float(jctx, tok, val); } -int json_obj_get_string(jparse_ctx_t *jctx, char *name, char *val, int size) +int json_obj_get_string(jparse_ctx_t *jctx, const char *name, char *val, int size) { json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_STRING); if (!tok) @@ -216,7 +216,7 @@ int json_obj_get_string(jparse_ctx_t *jctx, char *name, char *val, int size) return json_tok_to_string(jctx, tok, val, size); } -int json_obj_get_strlen(jparse_ctx_t *jctx, char *name, int *strlen) +int json_obj_get_strlen(jparse_ctx_t *jctx, const char *name, int *strlen) { json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_STRING); if (!tok) @@ -225,7 +225,7 @@ int json_obj_get_strlen(jparse_ctx_t *jctx, char *name, int *strlen) return OS_SUCCESS; } -int json_obj_get_object_str(jparse_ctx_t *jctx, char *name, char *val, int size) +int json_obj_get_object_str(jparse_ctx_t *jctx, const char *name, char *val, int size) { json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_OBJECT); if (!tok) @@ -233,7 +233,7 @@ int json_obj_get_object_str(jparse_ctx_t *jctx, char *name, char *val, int size) return json_tok_to_string(jctx, tok, val, size); } -int json_obj_get_object_strlen(jparse_ctx_t *jctx, char *name, int *strlen) +int json_obj_get_object_strlen(jparse_ctx_t *jctx, const char *name, int *strlen) { json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_OBJECT); if (!tok) @@ -241,7 +241,7 @@ int json_obj_get_object_strlen(jparse_ctx_t *jctx, char *name, int *strlen) *strlen = tok->end - tok->start; return OS_SUCCESS; } -int json_obj_get_array_str(jparse_ctx_t *jctx, char *name, char *val, int size) +int json_obj_get_array_str(jparse_ctx_t *jctx, const char *name, char *val, int size) { json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_ARRAY); if (!tok) @@ -249,7 +249,7 @@ int json_obj_get_array_str(jparse_ctx_t *jctx, char *name, char *val, int size) return json_tok_to_string(jctx, tok, val, size); } -int json_obj_get_array_strlen(jparse_ctx_t *jctx, char *name, int *strlen) +int json_obj_get_array_strlen(jparse_ctx_t *jctx, const char *name, int *strlen) { json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_ARRAY); if (!tok) diff --git a/lib/libesp32_div/ESP32-HomeKit/src/json_parser.h b/lib/libesp32_div/ESP32-HomeKit/src/json_parser.h index 3e982fe14..42163d7fc 100644 --- a/lib/libesp32_div/ESP32-HomeKit/src/json_parser.h +++ b/lib/libesp32_div/ESP32-HomeKit/src/json_parser.h @@ -43,20 +43,20 @@ typedef struct { int json_parse_start(jparse_ctx_t *jctx, char *js, int len); int json_parse_end(jparse_ctx_t *jctx); -int json_obj_get_array(jparse_ctx_t *jctx, char *name, int *num_elem); +int json_obj_get_array(jparse_ctx_t *jctx, const char *name, int *num_elem); int json_obj_leave_array(jparse_ctx_t *jctx); -int json_obj_get_object(jparse_ctx_t *jctx, char *name); +int json_obj_get_object(jparse_ctx_t *jctx, const char *name); int json_obj_leave_object(jparse_ctx_t *jctx); -int json_obj_get_bool(jparse_ctx_t *jctx, char *name, bool *val); -int json_obj_get_int(jparse_ctx_t *jctx, char *name, int *val); -int json_obj_get_int64(jparse_ctx_t *jctx, char *name, int64_t *val); -int json_obj_get_float(jparse_ctx_t *jctx, char *name, float *val); -int json_obj_get_string(jparse_ctx_t *jctx, char *name, char *val, int size); -int json_obj_get_strlen(jparse_ctx_t *jctx, char *name, int *strlen); -int json_obj_get_object_str(jparse_ctx_t *jctx, char *name, char *val, int size); -int json_obj_get_object_strlen(jparse_ctx_t *jctx, char *name, int *strlen); -int json_obj_get_array_str(jparse_ctx_t *jctx, char *name, char *val, int size); -int json_obj_get_array_strlen(jparse_ctx_t *jctx, char *name, int *strlen); +int json_obj_get_bool(jparse_ctx_t *jctx, const char *name, bool *val); +int json_obj_get_int(jparse_ctx_t *jctx, const char *name, int *val); +int json_obj_get_int64(jparse_ctx_t *jctx, const char *name, int64_t *val); +int json_obj_get_float(jparse_ctx_t *jctx, const char *name, float *val); +int json_obj_get_string(jparse_ctx_t *jctx, const char *name, char *val, int size); +int json_obj_get_strlen(jparse_ctx_t *jctx, const char *name, int *strlen); +int json_obj_get_object_str(jparse_ctx_t *jctx, const char *name, char *val, int size); +int json_obj_get_object_strlen(jparse_ctx_t *jctx, const char *name, int *strlen); +int json_obj_get_array_str(jparse_ctx_t *jctx, const char *name, char *val, int size); +int json_obj_get_array_strlen(jparse_ctx_t *jctx, const char *name, int *strlen); int json_arr_get_array(jparse_ctx_t *jctx, uint32_t index); int json_arr_leave_array(jparse_ctx_t *jctx); diff --git a/lib/libesp32_div/ESP32-HomeKit/src/mu_srp.c b/lib/libesp32_div/ESP32-HomeKit/src/mu_srp.c index 7a14b93e0..0b7ad0b98 100644 --- a/lib/libesp32_div/ESP32-HomeKit/src/mu_srp.c +++ b/lib/libesp32_div/ESP32-HomeKit/src/mu_srp.c @@ -447,7 +447,7 @@ int mu_srp_get_session_key(mu_srp_handle_t *hd, char *bytes_A, int len_A, char * return -1; } -int mu_srp_exchange_proofs(mu_srp_handle_t *hd, char *username, char *bytes_user_proof, char *bytes_host_proof) +int mu_srp_exchange_proofs(mu_srp_handle_t *hd, const char *username, char *bytes_user_proof, char *bytes_host_proof) { /* First calculate M */ unsigned char hash_n[SHA512HashSize]; diff --git a/lib/libesp32_div/ESP32-HomeKit/src/mu_srp.h b/lib/libesp32_div/ESP32-HomeKit/src/mu_srp.h index 8463ea318..80883bc77 100644 --- a/lib/libesp32_div/ESP32-HomeKit/src/mu_srp.h +++ b/lib/libesp32_div/ESP32-HomeKit/src/mu_srp.h @@ -84,7 +84,7 @@ int mu_srp_get_session_key(mu_srp_handle_t *hd, char *bytes_A, int len_A, char * * bytes_user_proof is parameter in * bytes_host_proof is parameter out (should be SHA512_DIGEST_LENGTH) bytes in size */ -int mu_srp_exchange_proofs(mu_srp_handle_t *hd, char *username, char *bytes_user_proof, char *bytes_host_proof); +int mu_srp_exchange_proofs(mu_srp_handle_t *hd, const char *username, char *bytes_user_proof, char *bytes_host_proof); diff --git a/lib/libesp32_div/ESP32-HomeKit/src/port/bignum_ESP32.c b/lib/libesp32_div/ESP32-HomeKit/src/port/bignum_ESP32.c index 1a63ffe7f..52d9554b5 100644 --- a/lib/libesp32_div/ESP32-HomeKit/src/port/bignum_ESP32.c +++ b/lib/libesp32_div/ESP32-HomeKit/src/port/bignum_ESP32.c @@ -25,7 +25,7 @@ #if __has_include("esp_idf_version.h") #include "esp_idf_version.h" #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0) -#warning("IDF is 4 or later") +// #warning("IDF is 4 or later") #include "soc/hwcrypto_periph.h" #endif #endif diff --git a/lib/libesp32_div/ESP32-HomeKit/src/port/bignum_ESP32.h b/lib/libesp32_div/ESP32-HomeKit/src/port/bignum_ESP32.h index 90c3325b5..fa91a961f 100644 --- a/lib/libesp32_div/ESP32-HomeKit/src/port/bignum_ESP32.h +++ b/lib/libesp32_div/ESP32-HomeKit/src/port/bignum_ESP32.h @@ -79,4 +79,4 @@ void esp_mpi_release_hardware(void); int esp_mpi_mul_mpi_mod(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M); //#endif // CONFIG_MBEDTLS_HARDWARE_MPI -#endif CONFIG_IDF_TARGET_ESP32 +#endif //CONFIG_IDF_TARGET_ESP32 diff --git a/lib/libesp32_div/ESP32-HomeKit/src/port/esp_bignum.c b/lib/libesp32_div/ESP32-HomeKit/src/port/esp_bignum.c index 8d6936e60..2c0fb07ce 100644 --- a/lib/libesp32_div/ESP32-HomeKit/src/port/esp_bignum.c +++ b/lib/libesp32_div/ESP32-HomeKit/src/port/esp_bignum.c @@ -23,7 +23,7 @@ #if __has_include("esp_idf_version.h") #include "esp_idf_version.h" #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0) -#warning("IDF is 4 or later") +// #warning("IDF is 4 or later") #include "soc/hwcrypto_periph.h" #endif #endif diff --git a/lib/libesp32_div/ESP32-HomeKit/src/shatest.c b/lib/libesp32_div/ESP32-HomeKit/src/shatest.c index 3924a31d5..f2c9232b3 100644 --- a/lib/libesp32_div/ESP32-HomeKit/src/shatest.c +++ b/lib/libesp32_div/ESP32-HomeKit/src/shatest.c @@ -781,11 +781,11 @@ void printstr(const char *str, int len) */ void printxstr(const char *str, int len) { - char *sep = ""; + char sep[2] = {0}; for ( ; len-- > 0; str++) { printf("%s%c%c", sep, hexdigits[(*str >> 4) & 0xF], hexdigits[*str & 0xF]); - sep = " "; + sep[0] = ' '; } } @@ -866,7 +866,7 @@ void printResult(uint8_t *Message_Digest, int hashsize, putchar('\n'); } else if (printResults == PRINTBASE64) { unsigned char b; - char *sm = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + const char *sm = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" "0123456789+/"; for (i = 0; i < hashsize; i += 3) { putchar(sm[Message_Digest[i] >> 2]); diff --git a/pio-tools/add_c_flags.py b/pio-tools/add_c_flags.py deleted file mode 100644 index c93059b36..000000000 --- a/pio-tools/add_c_flags.py +++ /dev/null @@ -1,4 +0,0 @@ -Import("env") - -# General options that are passed to the C compiler (C only; not C++). -env.Append(CFLAGS=["-Wno-discarded-qualifiers"]) diff --git a/platformio.ini b/platformio.ini index 660bf4d96..fdb0e328a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -64,7 +64,6 @@ lib_extra_dirs = [scripts_defaults] extra_scripts = pio-tools/strip-floats.py - pio-tools/add_c_flags.py pio-tools/name-firmware.py pio-tools/gzip-firmware.py pio-tools/override_copy.py From 7c8bc70cb02dd39c238e68cf4aff84b575e7fee2 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 15 Nov 2021 12:58:53 +0100 Subject: [PATCH 028/185] overlooked delete not needed extra script anymore --- platformio_tasmota32.ini | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index ace874df4..4a5299368 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -30,8 +30,6 @@ build_flags = ${esp_defaults.build_flags} -include "esp32x_fixes.h" ; wrappers for the crash-recorder -Wl,--wrap=panicHandler -Wl,--wrap=xt_unhandled_exception -extra_scripts = ${common.extra_scripts} - pre:pio-tools/add_c_flags.py [core32] platform = https://github.com/platformio/platform-espressif32.git#feature/arduino-idf-master @@ -48,4 +46,4 @@ platform_packages = framework-arduinoespressif32 @ https://github.com/ platformio/tool-esptoolpy @ https://github.com/tasmota/esptool/releases/download/v3.2/esptool-v3.2.zip platformio/tool-mklittlefs @ ~1.203.200522 build_unflags = ${esp32_defaults.build_unflags} -build_flags = ${esp32_defaults.build_flags} \ No newline at end of file +build_flags = ${esp32_defaults.build_flags} From 7442ae8f474f475b9f1ae0b6e04df1f08229f09c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 15 Nov 2021 14:36:42 +0100 Subject: [PATCH 029/185] Enable Berry in bluetooth env since it is now enough free RAM with latest framework. --- tasmota/tasmota_configurations_ESP32.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/tasmota_configurations_ESP32.h b/tasmota/tasmota_configurations_ESP32.h index dc2ad62fa..b708201d7 100644 --- a/tasmota/tasmota_configurations_ESP32.h +++ b/tasmota/tasmota_configurations_ESP32.h @@ -171,7 +171,7 @@ #define USE_SDCARD #define USE_ADC -#undef USE_BERRY // Disable Berry scripting language +//#undef USE_BERRY // Disable Berry scripting language #define USE_BLE_ESP32 // Enable new BLE driver #define USE_EQ3_ESP32 #define USE_MI_ESP32 // (ESP32 only) Add support for ESP32 as a BLE-bridge (+9k2 mem, +292k flash) From 6d47bfc46ebb31ab2a797cedd2b9f68af8e1fe4e Mon Sep 17 00:00:00 2001 From: stefanbode Date: Mon, 15 Nov 2021 17:31:15 +0100 Subject: [PATCH 030/185] internal_dev --- tasmota/xdrv_27_shutter.ino | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index de3f20239..fd781e03f 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -345,7 +345,7 @@ void ShutterInit(void) break; } AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d min realpos_chg: %d, min tilt_chg %d"),i+1,Shutter[i].min_realPositionChange,Shutter[i].min_TiltChange); - //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d Openvel %d, Closevel: %d"),i, ShutterGlobal.open_velocity_max, Shutter[i].close_velocity_max); + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d Openvel %d, Closevel: %d"),i, ShutterGlobal.open_velocity_max, Shutter[i].close_velocity_max); AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d Init. Pos %d, Inv %d, Locked %d, Endstop enab %d, webButt inv %d, Motordel: %d"), i+1, Shutter[i].real_position, (Settings->shutter_options[i]&1) ? 1 : 0, (Settings->shutter_options[i]&2) ? 1 : 0, (Settings->shutter_options[i]&4) ? 1 : 0, (Settings->shutter_options[i]&8) ? 1 : 0, Shutter[i].motordelay); @@ -529,11 +529,11 @@ void ShutterUpdatePosition(void) XdrvRulesProcess(0); ShutterGlobal.start_reported = 1; } - AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Time %d, cStop %d, cVelo %d, mVelo %d, aVelo %d, mRun %d, aPos %d, aPos2 %d, nStop %d, Trgt %d, mVelo %d, Dir %d, Tilt %d, TrgtTilt: %d, Tiltmove: %d"), - Shutter[i].time, current_stop_way, current_pwm_velocity, velocity_max, Shutter[i].accelerator, min_runtime_ms, current_real_position,Shutter[i].real_position, + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Time %d(%d), cStop %d, cVelo %d, mVelo %d, aVelo %d, mRun %d, aPos %d, aPos2 %d, nStop %d, Trgt %d, mVelo %d, Dir %d, Tilt %d, TrgtTilt: %d, Tiltmove: %d"), + Shutter[i].time, Shutter[i].time-Shutter[i].pwm_value,current_stop_way, current_pwm_velocity, velocity_max, Shutter[i].accelerator, min_runtime_ms, current_real_position,Shutter[i].real_position, next_possible_stop_position, Shutter[i].target_position, velocity_change_per_step_max, Shutter[i].direction,Shutter[i].tilt_real_pos, Shutter[i].tilt_target_pos, Shutter[i].tiltmoving); - + Shutter[i].pwm_value = Shutter[i].time; if ( ((Shutter[i].real_position * Shutter[i].direction >= Shutter[i].target_position * Shutter[i].direction && Shutter[i].tiltmoving==0) || ((int16_t)Shutter[i].tilt_real_pos * Shutter[i].direction * Shutter[i].tilt_config[2] >= (int16_t)Shutter[i].tilt_target_pos * Shutter[i].direction * Shutter[i].tilt_config[2] && Shutter[i].tiltmoving==1)) || (ShutterGlobal.position_mode == SHT_COUNTER && Shutter[i].accelerator <0 && Shutter[i].pwm_velocity+Shutter[i].accelerator=<%s>, max10s?"),i+1, rules_vars[i]); + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Delay Start? var%d <99>=<%s>, max10s?"),i+1, rules_vars[i]); TasmotaGlobal.rules_flag.shutter_moving = 1; XdrvRulesProcess(0); uptime_Local = TasmotaGlobal.uptime; while (uptime_Local+10 > TasmotaGlobal.uptime && (String)rules_vars[i] == "99") { loop(); } - AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Delay Start. Done")); + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Delay Start. Done")); #endif // USE_RULES } From 0cc6f85634446d0f0edcb55a76fcf21c615ad0ea Mon Sep 17 00:00:00 2001 From: stefanbode Date: Mon, 15 Nov 2021 18:12:14 +0100 Subject: [PATCH 031/185] Update xdrv_27_shutter.ino --- tasmota/xdrv_27_shutter.ino | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index fd781e03f..59d2202cb 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -102,6 +102,7 @@ struct SHUTTER { uint16_t venetian_delay = 0; // Delay in steps before venetian shutter start physical moving. Based on tilt position uint16_t min_realPositionChange = 0; // minimum change of the position before the shutter operates. different for PWM and time based operations uint16_t min_TiltChange = 0; // minimum change of the tilt before the shutter operates. different for PWM and time based operations + uint16_t missed_steps =0; } Shutter[MAX_SHUTTERS]; struct SHUTTERGLOBAL { @@ -530,10 +531,10 @@ void ShutterUpdatePosition(void) ShutterGlobal.start_reported = 1; } AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Time %d(%d), cStop %d, cVelo %d, mVelo %d, aVelo %d, mRun %d, aPos %d, aPos2 %d, nStop %d, Trgt %d, mVelo %d, Dir %d, Tilt %d, TrgtTilt: %d, Tiltmove: %d"), - Shutter[i].time, Shutter[i].time-Shutter[i].pwm_value,current_stop_way, current_pwm_velocity, velocity_max, Shutter[i].accelerator, min_runtime_ms, current_real_position,Shutter[i].real_position, + Shutter[i].time, Shutter[i].time-Shutter[i].missed_steps,current_stop_way, current_pwm_velocity, velocity_max, Shutter[i].accelerator, min_runtime_ms, current_real_position,Shutter[i].real_position, next_possible_stop_position, Shutter[i].target_position, velocity_change_per_step_max, Shutter[i].direction,Shutter[i].tilt_real_pos, Shutter[i].tilt_target_pos, Shutter[i].tiltmoving); - Shutter[i].pwm_value = Shutter[i].time; + Shutter[i].missed_steps = Shutter[i].time+1; if ( ((Shutter[i].real_position * Shutter[i].direction >= Shutter[i].target_position * Shutter[i].direction && Shutter[i].tiltmoving==0) || ((int16_t)Shutter[i].tilt_real_pos * Shutter[i].direction * Shutter[i].tilt_config[2] >= (int16_t)Shutter[i].tilt_target_pos * Shutter[i].direction * Shutter[i].tilt_config[2] && Shutter[i].tiltmoving==1)) || (ShutterGlobal.position_mode == SHT_COUNTER && Shutter[i].accelerator <0 && Shutter[i].pwm_velocity+Shutter[i].accelerator Date: Mon, 15 Nov 2021 18:43:11 +0100 Subject: [PATCH 032/185] Update xdrv_27_shutter.ino --- tasmota/xdrv_27_shutter.ino | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 59d2202cb..0722622eb 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -557,8 +557,7 @@ void ShutterUpdatePosition(void) CmndShutterPosition(); return; } else { - Settings->shutter_tilt_pos[i] = Shutter[i].tilt_real_pos; - Shutter[i].tiltmoving = 0; + Settings->shutter_tilt_pos[i] = Shutter[i].tilt_real_pos; } ShutterLogPos(i); @@ -1151,8 +1150,10 @@ void CmndShutterPosition(void) int8_t new_shutterdirection; if (abs(Shutter[index].target_position - Shutter[index].real_position ) > Shutter[index].min_realPositionChange) { new_shutterdirection = Shutter[index].real_position < Shutter[index].target_position ? 1 : -1; + Shutter[i].tiltmoving = 0; } else { new_shutterdirection = Shutter[index].tilt_real_pos < Shutter[index].tilt_target_pos ? 1 : -1; + Shutter[i].tiltmoving = 1; } if (Shutter[index].direction == -new_shutterdirection) { From a6b0cf9d318bc4b2210af265bf7bafe7aaed512a Mon Sep 17 00:00:00 2001 From: stefanbode Date: Mon, 15 Nov 2021 18:43:47 +0100 Subject: [PATCH 033/185] Update xdrv_27_shutter.ino --- tasmota/xdrv_27_shutter.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 0722622eb..86160b565 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -557,7 +557,7 @@ void ShutterUpdatePosition(void) CmndShutterPosition(); return; } else { - Settings->shutter_tilt_pos[i] = Shutter[i].tilt_real_pos; + Settings->shutter_tilt_pos[i] = Shutter[i].tilt_real_pos; } ShutterLogPos(i); @@ -1150,10 +1150,10 @@ void CmndShutterPosition(void) int8_t new_shutterdirection; if (abs(Shutter[index].target_position - Shutter[index].real_position ) > Shutter[index].min_realPositionChange) { new_shutterdirection = Shutter[index].real_position < Shutter[index].target_position ? 1 : -1; - Shutter[i].tiltmoving = 0; + Shutter[index].tiltmoving = 0; } else { new_shutterdirection = Shutter[index].tilt_real_pos < Shutter[index].tilt_target_pos ? 1 : -1; - Shutter[i].tiltmoving = 1; + Shutter[index].tiltmoving = 1; } if (Shutter[index].direction == -new_shutterdirection) { From a08b54b29557ff687b3c40c6800833a4dc949be5 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Mon, 15 Nov 2021 19:14:35 +0100 Subject: [PATCH 034/185] Fix Berry compound assignment --- lib/libesp32/Berry/src/be_code.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/libesp32/Berry/src/be_code.c b/lib/libesp32/Berry/src/be_code.c index 6a332bb07..3fac0bbcd 100644 --- a/lib/libesp32/Berry/src/be_code.c +++ b/lib/libesp32/Berry/src/be_code.c @@ -335,12 +335,15 @@ static void free_suffix(bfuncinfo *finfo, bexpdesc *e) } } -static int suffix_destreg(bfuncinfo *finfo, bexpdesc *e1, int dst) +static int suffix_destreg(bfuncinfo *finfo, bexpdesc *e1, int dst, bbool no_reg_reuse) { int cand_dst = dst; /* candidate for new dst */ int nlocal = be_list_count(finfo->local); int reg1 = (e1->v.ss.tt == ETREG) ? e1->v.ss.obj : -1; /* check if obj is ETREG or -1 */ int reg2 = (!isK(e1->v.ss.idx) && e1->v.ss.idx >= nlocal) ? e1->v.ss.idx : -1; /* check if idx is ETREG or -1 */ + if (no_reg_reuse) { /* if no_reg_reuse flag, then don't reuse any register, this is useful for compound assignments */ + reg1 = reg2 = -1; + } if (reg1 >= 0 && reg2 >= 0) { /* both are ETREG, we keep the lowest and discard the other */ @@ -364,9 +367,9 @@ static int suffix_destreg(bfuncinfo *finfo, bexpdesc *e1, int dst) return dst; } -static int code_suffix(bfuncinfo *finfo, bopcode op, bexpdesc *e, int dst) +static int code_suffix(bfuncinfo *finfo, bopcode op, bexpdesc *e, int dst, bbool no_reg_reuse) { - dst = suffix_destreg(finfo, e, dst); + dst = suffix_destreg(finfo, e, dst, no_reg_reuse); if (dst > finfo->freereg) { dst = finfo->freereg; } @@ -400,6 +403,7 @@ static bbool constint(bfuncinfo *finfo, bint i) /* At exit, If dst is `freereg`, the register is allocated */ static int var2reg(bfuncinfo *finfo, bexpdesc *e, int dst) { + bbool no_reg_reuse = (dst >= 0); /* if dst reg is explicitly specified, do not optimize register allocation */ if (dst < 0) { /* if unspecified, allocate a new register if needed */ dst = finfo->freereg; } @@ -434,10 +438,10 @@ static int var2reg(bfuncinfo *finfo, bexpdesc *e, int dst) codeABx(finfo, OP_GETUPV, dst, e->v.idx); break; case ETMEMBER: - dst = code_suffix(finfo, OP_GETMBR, e, dst); + dst = code_suffix(finfo, OP_GETMBR, e, dst, no_reg_reuse); break; case ETINDEX: - dst = code_suffix(finfo, OP_GETIDX, e, dst); + dst = code_suffix(finfo, OP_GETIDX, e, dst, no_reg_reuse); break; case ETLOCAL: case ETREG: case ETCONST: return e->v.idx; @@ -479,6 +483,7 @@ static int exp2reg(bfuncinfo *finfo, bexpdesc *e, int dst) /* Returns the destination register, guaranteed to be ETREG */ static int codedestreg(bfuncinfo *finfo, bexpdesc *e1, bexpdesc *e2, int dst) { + if (dst < 0) { dst = finfo->freereg; } int cand_dst = dst; int con1 = e1->type == ETREG, con2 = e2->type == ETREG; @@ -506,7 +511,6 @@ static int codedestreg(bfuncinfo *finfo, bexpdesc *e1, bexpdesc *e2, int dst) /* On exit, e1 is guaranteed to be ETREG, which may have been allocated */ static void binaryexp(bfuncinfo *finfo, bopcode op, bexpdesc *e1, bexpdesc *e2, int dst) { - if (dst < 0) { dst = finfo->freereg; } int src1 = exp2reg(finfo, e1, dst); /* potentially force the target for src1 reg */ int src2 = exp2anyreg(finfo, e2); dst = codedestreg(finfo, e1, e2, dst); @@ -720,7 +724,7 @@ int be_code_getmethod(bfuncinfo *finfo, bexpdesc *e) { int dst = finfo->freereg; be_assert(e->type == ETMEMBER); - dst = code_suffix(finfo, OP_GETMET, e, dst); + dst = code_suffix(finfo, OP_GETMET, e, dst, bfalse); /* method [object] args */ be_code_allocregs(finfo, dst == finfo->freereg ? 2 : 1); return dst; From 0e2ad05c2cbc2bd1bc8314d2b1b951d9168d0e0d Mon Sep 17 00:00:00 2001 From: stefanbode Date: Mon, 15 Nov 2021 19:52:48 +0100 Subject: [PATCH 035/185] Update xdrv_27_shutter.ino --- tasmota/xdrv_27_shutter.ino | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 86160b565..967ec860e 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -328,7 +328,7 @@ void ShutterInit(void) Shutter[i].tilt_config[k] = Settings->shutter_tilt_config[k][i]; } Shutter[i].tilt_real_pos = Settings->shutter_tilt_pos[i]; - Shutter[i].tilt_velocity = Shutter[i].tilt_config[2] > 0 ? (Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0])/Shutter[i].tilt_config[2] : 1; + Shutter[i].tilt_velocity = Shutter[i].tilt_config[2] > 0 ? ((Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0])/Shutter[i].tilt_config[2])+1 : 1; Shutter[i].close_velocity_max = ShutterGlobal.open_velocity_max*Shutter[i].open_time / Shutter[i].close_time; @@ -472,8 +472,11 @@ void ShutterDecellerateForStop(uint8_t i) void ShutterPowerOff(uint8_t i) { - AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Stop Shutter %d. Switchmode %d"), i+1,Shutter[i].switch_mode); // fix log to indicate correct shutter number + AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Stop %d. Mode %d, time:%d"), i+1,Shutter[i].switch_mode, Shutter[i].time); // fix log to indicate correct shutter number ShutterDecellerateForStop(i); + if (Shutter[i].direction !=0) { + Shutter[i].direction = 0; + } switch (Shutter[i].switch_mode) { case SHT_SWITCH: if ((1 << (Settings->shutter_startrelay[i]-1)) & TasmotaGlobal.power) { @@ -513,10 +516,7 @@ void ShutterPowerOff(uint8_t i) ExecuteCommand(scmnd, SRC_BUTTON); break; } - if (Shutter[i].direction !=0) { - Shutter[i].direction = 0; - delay(MOTOR_STOP_TIME); - } + delay(MOTOR_STOP_TIME); } void ShutterUpdatePosition(void) @@ -632,8 +632,8 @@ void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) if (Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0] != 0) { Shutter[i].venetian_delay = (Shutter[i].direction > 0 ? Shutter[i].tilt_config[1]-Shutter[i].tilt_real_pos : Shutter[i].tilt_real_pos-Shutter[i].tilt_config[0]) * Shutter[i].tilt_config[2] / (Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0]); //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: real %d, start %d, counter %d,freq_max %d, dir %d, freq %d"),Shutter[i].real_position, Shutter[i].start_position ,RtcSettings.pulse_counter[i],ShutterGlobal.open_velocity_max , Shutter[i].direction ,ShutterGlobal.open_velocity_max ); - //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: %d VenetianDelay: %d, Pos: %d, Dir: %d, Delta: %d, Durat: %d, Start: %d, Target: %d"), - // i, Shutter[i].venetian_delay, Shutter[i].tilt_real_pos,Shutter[i].direction,(Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0]), Shutter[i].tilt_config[2],Shutter[i].tilt_start_pos,Shutter[i].tilt_target_pos); + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: %d VenetianDelay: %d, Pos: %d, Dir: %d, Delta: %d, Durat: %d, Start: %d, Target: %d"), + i, Shutter[i].venetian_delay, Shutter[i].tilt_real_pos,Shutter[i].direction,(Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0]), Shutter[i].tilt_config[2],Shutter[i].tilt_start_pos,Shutter[i].tilt_target_pos); } } AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Start shtr%d from %d to %d in direction %d"), i, Shutter[i].start_position, Shutter[i].target_position, Shutter[i].direction); @@ -686,7 +686,7 @@ void ShutterRelayChanged(void) // SRC_IGNORE added because INTERLOCK function bite causes this as last source for changing the relay. //uint8 manual_relays_changed = ((ShutterGlobal.RelayCurrentMask >> (Settings->shutter_startrelay[i] -1)) & 3) && SRC_IGNORE != TasmotaGlobal.last_source && SRC_SHUTTER != TasmotaGlobal.last_source && SRC_PULSETIMER != TasmotaGlobal.last_source ; uint8 manual_relays_changed = ((ShutterGlobal.RelayCurrentMask >> (Settings->shutter_startrelay[i] -1)) & 3) && SRC_SHUTTER != TasmotaGlobal.last_source && SRC_PULSETIMER != TasmotaGlobal.last_source ; - AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d, Source %s, Powerstate %ld, RelayMask %d, ManualChange %d"), + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d, Source %s, Powerstate %ld, RelayMask %d, ManualChange %d"), i+1, GetTextIndexed(stemp1, sizeof(stemp1), TasmotaGlobal.last_source, kCommandSource), powerstate_local,ShutterGlobal.RelayCurrentMask,manual_relays_changed); if (manual_relays_changed) { //ShutterGlobal.skip_relay_change = true; From 46c4045ce1c55c5f92d05246edf2a985cd6828df Mon Sep 17 00:00:00 2001 From: stefanbode Date: Mon, 15 Nov 2021 19:55:04 +0100 Subject: [PATCH 036/185] Update xdrv_27_shutter.ino --- tasmota/xdrv_27_shutter.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 967ec860e..fcdff233c 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -687,7 +687,7 @@ void ShutterRelayChanged(void) //uint8 manual_relays_changed = ((ShutterGlobal.RelayCurrentMask >> (Settings->shutter_startrelay[i] -1)) & 3) && SRC_IGNORE != TasmotaGlobal.last_source && SRC_SHUTTER != TasmotaGlobal.last_source && SRC_PULSETIMER != TasmotaGlobal.last_source ; uint8 manual_relays_changed = ((ShutterGlobal.RelayCurrentMask >> (Settings->shutter_startrelay[i] -1)) & 3) && SRC_SHUTTER != TasmotaGlobal.last_source && SRC_PULSETIMER != TasmotaGlobal.last_source ; //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d, Source %s, Powerstate %ld, RelayMask %d, ManualChange %d"), - i+1, GetTextIndexed(stemp1, sizeof(stemp1), TasmotaGlobal.last_source, kCommandSource), powerstate_local,ShutterGlobal.RelayCurrentMask,manual_relays_changed); + // i+1, GetTextIndexed(stemp1, sizeof(stemp1), TasmotaGlobal.last_source, kCommandSource), powerstate_local,ShutterGlobal.RelayCurrentMask,manual_relays_changed); if (manual_relays_changed) { //ShutterGlobal.skip_relay_change = true; ShutterLimitRealAndTargetPositions(i); From a115f527a3b8b9ea2c6b6b844d4e0c5bbf4f8a60 Mon Sep 17 00:00:00 2001 From: StoyanDimitrov Date: Mon, 15 Nov 2021 20:23:10 +0000 Subject: [PATCH 037/185] Update Bulgariant translation Translation refinements. --- tasmota/language/bg_BG.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tasmota/language/bg_BG.h b/tasmota/language/bg_BG.h index 4c8478ea0..d4015f984 100644 --- a/tasmota/language/bg_BG.h +++ b/tasmota/language/bg_BG.h @@ -249,7 +249,7 @@ #define D_REDIRECTED "Пренасочено към портала за настройка" #define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager set AccessPoint and keep Station" #define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager set AccessPoint" -#define D_TRYING_TO_CONNECT "Извършва се опит за свързване на устройството към мрежата" +#define D_TRYING_TO_CONNECT "Oпит за свързване към избраната мрежа" #define D_RESTART_IN "Рестарт след" #define D_SECONDS "секунди" @@ -336,7 +336,7 @@ #define D_SINGLE_DEVICE "едно устройство" #define D_MULTI_DEVICE "много устройства" -#define D_CONFIGURE_TEMPLATE "Настройка на шаблона" +#define D_CONFIGURE_TEMPLATE "Настройки на шаблона" #define D_TEMPLATE_PARAMETERS "Параметри на шаблона" #define D_TEMPLATE_NAME "Име" #define D_BASE_TYPE "Основан на" @@ -364,7 +364,7 @@ #define D_ESP_CHIP_ID "ID на чипа на ESP" #define D_FLASH_CHIP_ID "ID на чипа на флаш-паметта" #define D_FLASH_CHIP_SIZE "Размер на флаш-паметта" -#define D_FREE_PROGRAM_SPACE "Свободно пространство за програми" +#define D_FREE_PROGRAM_SPACE "Свободно място за програми" #define D_UPGRADE_BY_WEBSERVER "Обновяване от сървър" #define D_OTA_URL "Адрес на сървър за OTA" @@ -376,7 +376,7 @@ #define D_UPLOAD_TRANSFER "Upload transfer" #define D_TRANSFER_STARTED "Transfer started" #define D_UPLOAD_ERR_1 "Не е избран файл" -#define D_UPLOAD_ERR_2 "Недостатъчно свободно пространство" +#define D_UPLOAD_ERR_2 "Недостатъчно свободно място" #define D_UPLOAD_ERR_3 "Недействителен подпис на файла" #define D_UPLOAD_ERR_4 "Размерът на програмата е по-голям от размера на флаш-паметта" #define D_UPLOAD_ERR_5 "Грешка при сравняване на буфери" @@ -413,11 +413,11 @@ #define D_WEMO_BASIC_EVENT "Основно събитие на WeMo" #define D_WEMO_EVENT_SERVICE "Услуга за събития на WeMo" #define D_WEMO_META_SERVICE "Мета-услуга на WeMo" -#define D_WEMO_SETUP "Настройка на WeMo" +#define D_WEMO_SETUP "Настройки на WeMo" #define D_RESPONSE_SENT "Отговорът е изпратен" #define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Настройка на Hue" +#define D_HUE_BRIDGE_SETUP "Настройки на Hue" #define D_HUE_API_NOT_IMPLEMENTED "ППИ на Hue не е реализиран" #define D_HUE_API "ППИ на Hue" #define D_HUE_POST_ARGS "Параметри на Hue по POST" @@ -442,18 +442,18 @@ #define D_DOMOTICZ_UPDATE_TIMER "Период на обновяване" // xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Настройка на графика" +#define D_CONFIGURE_TIMER "Настройки на график" #define D_TIMER_PARAMETERS "Параметри на графиците" #define D_TIMER_ENABLE "Използване на графици" #define D_TIMER_ARM "Включване" #define D_TIMER_TIME "Време" #define D_TIMER_DAYS "Дни" -#define D_TIMER_REPEAT "Периодичен" +#define D_TIMER_REPEAT "Повтаряне" #define D_TIMER_OUTPUT "Изход" #define D_TIMER_ACTION "Действие" // xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Настройка на KNX" +#define D_CONFIGURE_KNX "Настройки на KNX" #define D_KNX_PARAMETERS "Параметри на KNX" #define D_KNX_GENERAL_CONFIG "Основни" #define D_KNX_PHYSICAL_ADDRESS "Физически адрес" @@ -513,7 +513,7 @@ #define D_DOMOTICZ_SHUTTER "Щора" // xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Настройка на PCF8574" +#define D_CONFIGURE_PCF8574 "Настройки на PCF8574" #define D_PCF8574_PARAMETERS "Параметри на PCF8574" #define D_INVERT_PORTS "Размяна на портовете" #define D_DEVICE "Устройство" @@ -563,7 +563,7 @@ #define D_HX_CAL_DONE "Калибрирано" #define D_HX_CAL_FAIL "Грешка при калибриране" #define D_RESET_HX711 "Нулиране на везната" -#define D_CONFIGURE_HX711 "Настройка на везната" +#define D_CONFIGURE_HX711 "Настройки на везната" #define D_HX711_PARAMETERS "Параметри на везната" #define D_ITEM_WEIGHT "Тегло" #define D_REFERENCE_WEIGHT "Еталонна тежест" @@ -608,7 +608,7 @@ // tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Няма" -#define D_SENSOR_USER "Потребител" +#define D_SENSOR_USER "Потребителско" #define D_SENSOR_OPTION "Настройки" #define D_SENSOR_DHT11 "DHT11" #define D_SENSOR_AM2301 "AM2301" From 87490c5e94aa3377663d86d8b4a5abd3ac905827 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Mon, 15 Nov 2021 22:11:04 +0100 Subject: [PATCH 038/185] Renamed autoconf suffix --- lib/libesp32/Berry/default/be_autoconf_lib.c | 149 +++++++++--------- .../Berry/default/embedded/autoconf.be | 20 +-- lib/libesp32/Berry/src/be_code.c | 5 +- 3 files changed, 89 insertions(+), 85 deletions(-) diff --git a/lib/libesp32/Berry/default/be_autoconf_lib.c b/lib/libesp32/Berry/default/be_autoconf_lib.c index bec1382ea..9f638d6d7 100644 --- a/lib/libesp32/Berry/default/be_autoconf_lib.c +++ b/lib/libesp32/Berry/default/be_autoconf_lib.c @@ -40,10 +40,10 @@ be_local_closure(page_autoconf_ctl, /* name */ /* K16 */ be_nested_string("arg", 1047474471, 3), /* K17 */ be_nested_string("reset", 1695364032, 5), /* K18 */ be_nested_string("format", -1180859054, 6), - /* K19 */ be_nested_string("https://raw.githubusercontent.com/tasmota/autoconf/main/%s/%s_autoconf.zip", 2084253523, 74), + /* K19 */ be_nested_string("https://raw.githubusercontent.com/tasmota/autoconf/main/%s/%s.autoconf", -1551440987, 70), /* K20 */ be_nested_string("arch", -1342162999, 4), /* K21 */ be_nested_string("CFG: downloading '%s'", 589480701, 21), - /* K22 */ be_nested_string("%s_autoconf.zip", -1148460718, 15), + /* K22 */ be_nested_string("%s.autoconf", -734583772, 11), /* K23 */ be_nested_string("webclient", -218578150, 9), /* K24 */ be_nested_string("begin", 1748273790, 5), /* K25 */ be_nested_string("GET", -1763262857, 3), @@ -453,7 +453,7 @@ be_local_closure(page_autoconf_mgr, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[38]) { /* constants */ + ( &(const bvalue[39]) { /* constants */ /* K0 */ be_nested_string("webserver", 1572454038, 9), /* K1 */ be_nested_string("string", 398550328, 6), /* K2 */ be_nested_string("check_privileged_access", -602033328, 23), @@ -464,34 +464,35 @@ be_local_closure(page_autoconf_mgr, /* name */ /* K7 */ be_nested_string("

 (This feature requires an internet connection)

", -1575700810, 74), /* K8 */ be_nested_string("get_current_module_path", -1088293888, 23), /* K9 */ be_nested_string("tr", 1195724803, 2), - /* K10 */ be_nested_string("_", -636741266, 1), - /* K11 */ be_nested_string(" ", 621580159, 1), - /* K12 */ be_nested_string("_error", 1132109656, 6), - /* K13 */ be_nested_string("<Error: apply new or remove>", -1439459347, 34), - /* K14 */ be_nested_string("<None>", -1692801798, 12), - /* K15 */ be_nested_string("
", 842307168, 77), - /* K16 */ be_nested_string("format", -1180859054, 6), - /* K17 */ be_nested_string(" Current auto-configuration", -82466516, 82), - /* K18 */ be_nested_string("

Current configuration:

%s

", -179311535, 46), - /* K19 */ be_nested_string("

", 232646018, 57), - /* K21 */ be_nested_string("", -1147033080, 82), - /* K22 */ be_nested_string("

", -748395557, 11), - /* K23 */ be_nested_string("

", 2052843416, 25), - /* K24 */ be_nested_string(" Select new auto-configuration", 1926223891, 80), - /* K25 */ be_nested_string("

", -502554737, 94), - /* K27 */ be_nested_string("
", 1336654704, 49), - /* K28 */ be_nested_string("

", 1863865923, 16), - /* K34 */ be_nested_string("", 1205771629, 72), - /* K35 */ be_nested_string("content_button", 1956476087, 14), - /* K36 */ be_nested_string("BUTTON_CONFIGURATION", 70820856, 20), - /* K37 */ be_nested_string("content_stop", 658554751, 12), + /* K10 */ be_nested_string("get_current_module_name", -1915696556, 23), + /* K11 */ be_nested_string("_", -636741266, 1), + /* K12 */ be_nested_string(" ", 621580159, 1), + /* K13 */ be_nested_string("_error", 1132109656, 6), + /* K14 */ be_nested_string("<Error: apply new or remove>", -1439459347, 34), + /* K15 */ be_nested_string("<None>", -1692801798, 12), + /* K16 */ be_nested_string("
", 842307168, 77), + /* K17 */ be_nested_string("format", -1180859054, 6), + /* K18 */ be_nested_string(" Current auto-configuration", -82466516, 82), + /* K19 */ be_nested_string("

Current configuration:

%s

", -179311535, 46), + /* K20 */ be_nested_string("

", 232646018, 57), + /* K22 */ be_nested_string("", -1147033080, 82), + /* K23 */ be_nested_string("

", -748395557, 11), + /* K24 */ be_nested_string("

", 2052843416, 25), + /* K25 */ be_nested_string(" Select new auto-configuration", 1926223891, 80), + /* K26 */ be_nested_string("

", -502554737, 94), + /* K28 */ be_nested_string("
", 1336654704, 49), + /* K29 */ be_nested_string("

", 1863865923, 16), + /* K35 */ be_nested_string("", 1205771629, 72), + /* K36 */ be_nested_string("content_button", 1956476087, 14), + /* K37 */ be_nested_string("BUTTON_CONFIGURATION", 70820856, 20), + /* K38 */ be_nested_string("content_stop", 658554751, 12), }), (be_nested_const_str("page_autoconf_mgr", -651030265, 17)), ((bstring*) &be_const_str_input), @@ -515,71 +516,71 @@ be_local_closure(page_autoconf_mgr, /* name */ 0x7C0C0200, // 0010 CALL R3 1 0x780E0006, // 0011 JMPF R3 #0019 0x8C100509, // 0012 GETMET R4 R2 K9 - 0x8C180108, // 0013 GETMET R6 R0 K8 + 0x8C18010A, // 0013 GETMET R6 R0 K10 0x7C180200, // 0014 CALL R6 1 - 0x581C000A, // 0015 LDCONST R7 K10 - 0x5820000B, // 0016 LDCONST R8 K11 + 0x581C000B, // 0015 LDCONST R7 K11 + 0x5820000C, // 0016 LDCONST R8 K12 0x7C100800, // 0017 CALL R4 4 0x70020004, // 0018 JMP #001E - 0x8810010C, // 0019 GETMBR R4 R0 K12 + 0x8810010D, // 0019 GETMBR R4 R0 K13 0x78120001, // 001A JMPF R4 #001D - 0x5810000D, // 001B LDCONST R4 K13 + 0x5810000E, // 001B LDCONST R4 K14 0x70020000, // 001C JMP #001E - 0x5810000E, // 001D LDCONST R4 K14 + 0x5810000F, // 001D LDCONST R4 K15 0x8C140306, // 001E GETMET R5 R1 K6 - 0x581C000F, // 001F LDCONST R7 K15 + 0x581C0010, // 001F LDCONST R7 K16 0x7C140400, // 0020 CALL R5 2 0x8C140306, // 0021 GETMET R5 R1 K6 - 0x8C1C0510, // 0022 GETMET R7 R2 K16 - 0x58240011, // 0023 LDCONST R9 K17 + 0x8C1C0511, // 0022 GETMET R7 R2 K17 + 0x58240012, // 0023 LDCONST R9 K18 0x7C1C0400, // 0024 CALL R7 2 0x7C140400, // 0025 CALL R5 2 0x8C140306, // 0026 GETMET R5 R1 K6 - 0x8C1C0510, // 0027 GETMET R7 R2 K16 - 0x58240012, // 0028 LDCONST R9 K18 + 0x8C1C0511, // 0027 GETMET R7 R2 K17 + 0x58240013, // 0028 LDCONST R9 K19 0x5C280800, // 0029 MOVE R10 R4 0x7C1C0600, // 002A CALL R7 3 0x7C140400, // 002B CALL R5 2 0x780E000B, // 002C JMPF R3 #0039 0x8C140306, // 002D GETMET R5 R1 K6 - 0x581C0013, // 002E LDCONST R7 K19 + 0x581C0014, // 002E LDCONST R7 K20 0x7C140400, // 002F CALL R5 2 0x8C140306, // 0030 GETMET R5 R1 K6 - 0x581C0014, // 0031 LDCONST R7 K20 + 0x581C0015, // 0031 LDCONST R7 K21 0x7C140400, // 0032 CALL R5 2 0x8C140306, // 0033 GETMET R5 R1 K6 - 0x581C0015, // 0034 LDCONST R7 K21 + 0x581C0016, // 0034 LDCONST R7 K22 0x7C140400, // 0035 CALL R5 2 0x8C140306, // 0036 GETMET R5 R1 K6 - 0x581C0016, // 0037 LDCONST R7 K22 + 0x581C0017, // 0037 LDCONST R7 K23 0x7C140400, // 0038 CALL R5 2 0x8C140306, // 0039 GETMET R5 R1 K6 - 0x581C0017, // 003A LDCONST R7 K23 + 0x581C0018, // 003A LDCONST R7 K24 0x7C140400, // 003B CALL R5 2 0x8C140306, // 003C GETMET R5 R1 K6 - 0x581C000F, // 003D LDCONST R7 K15 + 0x581C0010, // 003D LDCONST R7 K16 0x7C140400, // 003E CALL R5 2 0x8C140306, // 003F GETMET R5 R1 K6 - 0x8C1C0510, // 0040 GETMET R7 R2 K16 - 0x58240018, // 0041 LDCONST R9 K24 + 0x8C1C0511, // 0040 GETMET R7 R2 K17 + 0x58240019, // 0041 LDCONST R9 K25 0x7C1C0400, // 0042 CALL R7 2 0x7C140400, // 0043 CALL R5 2 0x8C140306, // 0044 GETMET R5 R1 K6 - 0x581C0019, // 0045 LDCONST R7 K25 + 0x581C001A, // 0045 LDCONST R7 K26 0x7C140400, // 0046 CALL R5 2 0x8C140306, // 0047 GETMET R5 R1 K6 - 0x581C001A, // 0048 LDCONST R7 K26 + 0x581C001B, // 0048 LDCONST R7 K27 0x7C140400, // 0049 CALL R5 2 0x8C140306, // 004A GETMET R5 R1 K6 - 0x581C001B, // 004B LDCONST R7 K27 + 0x581C001C, // 004B LDCONST R7 K28 0x7C140400, // 004C CALL R5 2 0x8C140306, // 004D GETMET R5 R1 K6 - 0x581C001C, // 004E LDCONST R7 K28 + 0x581C001D, // 004E LDCONST R7 K29 0x7C140400, // 004F CALL R5 2 - 0x8C14011D, // 0050 GETMET R5 R0 K29 + 0x8C14011E, // 0050 GETMET R5 R0 K30 0x7C140200, // 0051 CALL R5 1 0x8C180306, // 0052 GETMET R6 R1 K6 - 0x5820001E, // 0053 LDCONST R8 K30 + 0x5820001F, // 0053 LDCONST R8 K31 0x7C180400, // 0054 CALL R6 2 0x60180010, // 0055 GETGBL R6 G16 0x5C1C0A00, // 0056 MOVE R7 R5 @@ -588,36 +589,36 @@ be_local_closure(page_autoconf_mgr, /* name */ 0x5C1C0C00, // 0059 MOVE R7 R6 0x7C1C0000, // 005A CALL R7 0 0x8C200306, // 005B GETMET R8 R1 K6 - 0x8C280510, // 005C GETMET R10 R2 K16 - 0x5830001F, // 005D LDCONST R12 K31 + 0x8C280511, // 005C GETMET R10 R2 K17 + 0x58300020, // 005D LDCONST R12 K32 0x5C340E00, // 005E MOVE R13 R7 0x8C380509, // 005F GETMET R14 R2 K9 0x5C400E00, // 0060 MOVE R16 R7 - 0x5844000A, // 0061 LDCONST R17 K10 - 0x5848000B, // 0062 LDCONST R18 K11 + 0x5844000B, // 0061 LDCONST R17 K11 + 0x5848000C, // 0062 LDCONST R18 K12 0x7C380800, // 0063 CALL R14 4 0x7C280800, // 0064 CALL R10 4 0x7C200400, // 0065 CALL R8 2 0x7001FFF1, // 0066 JMP #0059 - 0x58180020, // 0067 LDCONST R6 K32 + 0x58180021, // 0067 LDCONST R6 K33 0xAC180200, // 0068 CATCH R6 1 0 0xB0080000, // 0069 RAISE 2 R0 R0 0x8C180306, // 006A GETMET R6 R1 K6 - 0x58200021, // 006B LDCONST R8 K33 + 0x58200022, // 006B LDCONST R8 K34 0x7C180400, // 006C CALL R6 2 0x8C180306, // 006D GETMET R6 R1 K6 - 0x58200022, // 006E LDCONST R8 K34 + 0x58200023, // 006E LDCONST R8 K35 0x7C180400, // 006F CALL R6 2 0x8C180306, // 0070 GETMET R6 R1 K6 - 0x58200016, // 0071 LDCONST R8 K22 + 0x58200017, // 0071 LDCONST R8 K23 0x7C180400, // 0072 CALL R6 2 0x8C180306, // 0073 GETMET R6 R1 K6 - 0x58200017, // 0074 LDCONST R8 K23 + 0x58200018, // 0074 LDCONST R8 K24 0x7C180400, // 0075 CALL R6 2 - 0x8C180323, // 0076 GETMET R6 R1 K35 - 0x88200324, // 0077 GETMBR R8 R1 K36 + 0x8C180324, // 0076 GETMET R6 R1 K36 + 0x88200325, // 0077 GETMBR R8 R1 K37 0x7C180400, // 0078 CALL R6 2 - 0x8C180325, // 0079 GETMET R6 R1 K37 + 0x8C180326, // 0079 GETMET R6 R1 K38 0x7C180200, // 007A CALL R6 1 0x80000000, // 007B RET 0 }) @@ -646,7 +647,7 @@ be_local_closure(get_current_module_name, /* name */ (be_nested_const_str("get_current_module_name", -1915696556, 23)), ((bstring*) &be_const_str_input), ( &(const binstruction[ 5]) { /* code */ - 0x5405FFF2, // 0000 LDINT R1 -13 + 0x5405FFF5, // 0000 LDINT R1 -10 0x40060201, // 0001 CONNECT R1 K1 R1 0x88080100, // 0002 GETMBR R2 R0 K0 0x94040401, // 0003 GETIDX R1 R2 R1 @@ -676,7 +677,7 @@ be_local_closure(delete_all_configs, /* name */ /* K2 */ be_nested_string("listdir", 2005220720, 7), /* K3 */ be_nested_string("/", 705468254, 1), /* K4 */ be_nested_string("find", -1108310694, 4), - /* K5 */ be_nested_string("_autoconf.zip", 1641927766, 13), + /* K5 */ be_nested_string(".autoconf", -1770288208, 9), /* K6 */ be_const_int(0), /* K7 */ be_nested_string("remove", -611183107, 6), /* K8 */ be_nested_string("stop_iteration", -121173395, 14), @@ -782,7 +783,7 @@ be_local_closure(load_templates, /* name */ /* K16 */ be_nested_string("load", -435725847, 4), /* K17 */ be_nested_string("CFG: loaded '%s'", 1699028828, 16), /* K18 */ be_nested_string("find", -1108310694, 4), - /* K19 */ be_nested_string("zip", -1417514060, 3), + /* K19 */ be_nested_string("files", 1055342736, 5), /* K20 */ be_nested_string("CFG: exception '%s' - '%s'", -199559383, 26), }), (be_nested_const_str("load_templates", -781097163, 14)), @@ -969,12 +970,12 @@ be_local_closure(init, /* name */ /* K5 */ be_nested_string("add_driver", 1654458371, 10), /* K6 */ be_const_int(0), /* K7 */ be_nested_string("find", -1108310694, 4), - /* K8 */ be_nested_string("_autoconf.zip", 1641927766, 13), + /* K8 */ be_nested_string(".autoconf", -1770288208, 9), /* K9 */ be_nested_string("format", -1180859054, 6), /* K10 */ be_nested_string("CFG: multiple autoconf files found, aborting ('%s' + '%s')", 197663371, 58), /* K11 */ be_nested_string("_error", 1132109656, 6), /* K12 */ be_const_int(1), - /* K13 */ be_nested_string("CFG: no '*_autoconf.zip' file found", -1047382425, 35), + /* K13 */ be_nested_string("CFG: no '*.autoconf' file found", 127493957, 31), /* K14 */ be_nested_string("_archive", -290407892, 8), }), (be_nested_const_str("init", 380752755, 4)), @@ -1115,7 +1116,7 @@ be_local_closure(reset, /* name */ /* K3 */ be_nested_string("/", 705468254, 1), /* K4 */ be_const_int(0), /* K5 */ be_nested_string("find", -1108310694, 4), - /* K6 */ be_nested_string("_autoconf.zip", 1641927766, 13), + /* K6 */ be_nested_string(".autoconf", -1770288208, 9), /* K7 */ be_nested_string("remove", -611183107, 6), /* K8 */ be_nested_string("format", -1180859054, 6), /* K9 */ be_nested_string("CFG: removed file '%s'", 2048602473, 22), diff --git a/lib/libesp32/Berry/default/embedded/autoconf.be b/lib/libesp32/Berry/default/embedded/autoconf.be index 3be35fe1e..3f9586e04 100644 --- a/lib/libesp32/Berry/default/embedded/autoconf.be +++ b/lib/libesp32/Berry/default/embedded/autoconf.be @@ -36,7 +36,7 @@ autoconf_module.init = def (m) var i = 0 while i < size(dir) - if string.find(dir[i], "_autoconf.zip") > 0 # does the file contain '*_autoconf.zip' + if string.find(dir[i], ".autoconf") > 0 # does the file contain '*.autoconf', >0 to skip `.autoconf` if entry != nil # we have multiple configuration files, not allowed print(string.format("CFG: multiple autoconf files found, aborting ('%s' + '%s')", entry, dir[i])) @@ -49,7 +49,7 @@ autoconf_module.init = def (m) end if entry == nil - print("CFG: no '*_autoconf.zip' file found") + print("CFG: no '*.autoconf' file found") return nil end @@ -82,7 +82,7 @@ autoconf_module.init = def (m) var dir = path.listdir("/") for d:dir - if string.find(d, "_autoconf.zip") > 0 # does the file contain '*_autoconf.zip' + if string.find(d, ".autoconf") > 0 # does the file contain '*.autoconf' path.remove(d) end end @@ -90,14 +90,14 @@ autoconf_module.init = def (m) # #################################################################################################### # Get current module - # contains the name of the archive without leading `/`, ex: `M5Stack_Fire_autoconf.zip` + # contains the name of the archive without leading `/`, ex: `M5Stack_Fire.autoconf` # or `nil` if none # #################################################################################################### def get_current_module_path() return self._archive end def get_current_module_name() - return self._archive[0..-13] + return self._archive[0..-10] end # #################################################################################################### @@ -123,7 +123,7 @@ autoconf_module.init = def (m) var j = json.load(s) tasmota.log(string.format("CFG: loaded '%s'", str(j)), 3) - var t = j.find("zip") + var t = j.find("files") if isinstance(t, list) return t end @@ -156,7 +156,7 @@ autoconf_module.init = def (m) webserver.content_send("

 (This feature requires an internet connection)

") var cur_module = self.get_current_module_path() - var cur_module_display = cur_module ? string.tr(self.get_current_module_path(), "_", " ") : self._error ? "<Error: apply new or remove>" : "<None>" + var cur_module_display = cur_module ? string.tr(self.get_current_module_name(), "_", " ") : self._error ? "<Error: apply new or remove>" : "<None>" webserver.content_send("
") webserver.content_send(string.format(" Current auto-configuration")) @@ -227,10 +227,10 @@ autoconf_module.init = def (m) var arch_name = webserver.arg("zip") if arch_name != "reset" - var url = string.format("https://raw.githubusercontent.com/tasmota/autoconf/main/%s/%s_autoconf.zip", tasmota.arch(), arch_name) + var url = string.format("https://raw.githubusercontent.com/tasmota/autoconf/main/%s/%s.autoconf", tasmota.arch(), arch_name) tasmota.log(string.format("CFG: downloading '%s'", url), 2); - var local_file = string.format("%s_autoconf.zip", arch_name) + var local_file = string.format("%s.autoconf", arch_name) # download file and write directly to file system var cl = webclient() @@ -282,7 +282,7 @@ autoconf_module.init = def (m) var i = 0 while i < size(dir) var fname = dir[i] - if string.find(fname, "_autoconf.zip") > 0 # does the file contain '*_autoconf.zip' + if string.find(fname, ".autoconf") > 0 # does the file contain '*.autoconf' path.remove(fname) print(string.format("CFG: removed file '%s'", fname)) end diff --git a/lib/libesp32/Berry/src/be_code.c b/lib/libesp32/Berry/src/be_code.c index 3fac0bbcd..40e067265 100644 --- a/lib/libesp32/Berry/src/be_code.c +++ b/lib/libesp32/Berry/src/be_code.c @@ -565,7 +565,10 @@ static void unaryexp(bfuncinfo *finfo, bopcode op, bexpdesc *e) { int src = exp2anyreg(finfo, e); int dst = e->type == ETREG ? src : be_code_allocregs(finfo, 1); - codeABC(finfo, op, dst, src, 0); + if (!(op == OP_MOVE && src == dst)) { + /* skip if MOVE from same src / dst */ + codeABC(finfo, op, dst, src, 0); + } e->type = ETREG; e->v.idx = dst; } From b3796c4adb9a51fbc8298bcbbc5e195bc61cbfeb Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Mon, 15 Nov 2021 23:06:04 +0100 Subject: [PATCH 039/185] Preliminary support for Tasmota Application (.tapp files) --- lib/libesp32/Berry/default/be_modtab.c | 2 + lib/libesp32/Berry/default/be_tapp_lib.c | 164 ++++++++++++++++++++ lib/libesp32/Berry/default/embedded/tapp.be | 35 +++++ tasmota/xdrv_52_7_berry_embedded.ino | 2 + tasmota/xdrv_52_9_berry.ino | 3 + 5 files changed, 206 insertions(+) create mode 100644 lib/libesp32/Berry/default/be_tapp_lib.c create mode 100644 lib/libesp32/Berry/default/embedded/tapp.be diff --git a/lib/libesp32/Berry/default/be_modtab.c b/lib/libesp32/Berry/default/be_modtab.c index 1b219658f..7e1a1bad9 100644 --- a/lib/libesp32/Berry/default/be_modtab.c +++ b/lib/libesp32/Berry/default/be_modtab.c @@ -27,6 +27,7 @@ be_extern_native_module(strict); be_extern_native_module(python_compat); be_extern_native_module(persist); be_extern_native_module(autoconf); +be_extern_native_module(tapp); be_extern_native_module(light); be_extern_native_module(gpio); be_extern_native_module(display); @@ -90,6 +91,7 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = { #ifdef USE_AUTOCONF &be_native_module(autoconf), #endif // USE_AUTOCONF + &be_native_module(tapp), &be_native_module(gpio), #ifdef USE_DISPLAY &be_native_module(display), diff --git a/lib/libesp32/Berry/default/be_tapp_lib.c b/lib/libesp32/Berry/default/be_tapp_lib.c new file mode 100644 index 000000000..7a8cbe693 --- /dev/null +++ b/lib/libesp32/Berry/default/be_tapp_lib.c @@ -0,0 +1,164 @@ +/******************************************************************** + * Tasmota App manager + * + * To use: `import tapp` + * + *******************************************************************/ +#include "be_constobj.h" + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(init, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_string("tasmota", 424643812, 7), + /* K1 */ be_nested_string("add_driver", 1654458371, 10), + }), + (be_nested_const_str("init", 380752755, 4)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 5]) { /* code */ + 0xB8060000, // 0000 GETNGBL R1 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x5C0C0000, // 0002 MOVE R3 R0 + 0x7C040400, // 0003 CALL R1 2 + 0x80000000, // 0004 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: autoexec +********************************************************************/ +be_local_closure(autoexec, /* name */ + be_nested_proto( + 11, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[13]) { /* constants */ + /* K0 */ be_nested_string("path", -2071507658, 4), + /* K1 */ be_nested_string("string", 398550328, 6), + /* K2 */ be_nested_string("listdir", 2005220720, 7), + /* K3 */ be_nested_string("/", 705468254, 1), + /* K4 */ be_nested_string("find", -1108310694, 4), + /* K5 */ be_nested_string(".tapp", 1363391594, 5), + /* K6 */ be_const_int(0), + /* K7 */ be_nested_string("format", -1180859054, 6), + /* K8 */ be_nested_string("TAP: found Tasmota App '%s'", -1651814898, 27), + /* K9 */ be_nested_string("tasmota", 424643812, 7), + /* K10 */ be_nested_string("load", -435725847, 4), + /* K11 */ be_nested_string("#autoexec.be", 1181757091, 12), + /* K12 */ be_nested_string("stop_iteration", -121173395, 14), + }), + (be_nested_const_str("autoexec", -618105405, 8)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[32]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0xA40A0200, // 0001 IMPORT R2 K1 + 0x8C0C0302, // 0002 GETMET R3 R1 K2 + 0x58140003, // 0003 LDCONST R5 K3 + 0x7C0C0400, // 0004 CALL R3 2 + 0x60100010, // 0005 GETGBL R4 G16 + 0x5C140600, // 0006 MOVE R5 R3 + 0x7C100200, // 0007 CALL R4 1 + 0xA8020012, // 0008 EXBLK 0 #001C + 0x5C140800, // 0009 MOVE R5 R4 + 0x7C140000, // 000A CALL R5 0 + 0x8C180504, // 000B GETMET R6 R2 K4 + 0x5C200A00, // 000C MOVE R8 R5 + 0x58240005, // 000D LDCONST R9 K5 + 0x7C180600, // 000E CALL R6 3 + 0x24180D06, // 000F GT R6 R6 K6 + 0x781A0009, // 0010 JMPF R6 #001B + 0x60180001, // 0011 GETGBL R6 G1 + 0x8C1C0507, // 0012 GETMET R7 R2 K7 + 0x58240008, // 0013 LDCONST R9 K8 + 0x5C280A00, // 0014 MOVE R10 R5 + 0x7C1C0600, // 0015 CALL R7 3 + 0x7C180200, // 0016 CALL R6 1 + 0xB81A1200, // 0017 GETNGBL R6 K9 + 0x8C180D0A, // 0018 GETMET R6 R6 K10 + 0x00200B0B, // 0019 ADD R8 R5 K11 + 0x7C180400, // 001A CALL R6 2 + 0x7001FFEC, // 001B JMP #0009 + 0x5810000C, // 001C LDCONST R4 K12 + 0xAC100200, // 001D CATCH R4 1 0 + 0xB0080000, // 001E RAISE 2 R0 R0 + 0x80000000, // 001F RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Tapp +********************************************************************/ +be_local_class(Tapp, + 0, + NULL, + be_nested_map(2, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_nested_key("init", 380752755, 4, -1), be_const_closure(init_closure) }, + { be_nested_key("autoexec", -618105405, 8, 0), be_const_closure(autoexec_closure) }, + })), + (be_nested_const_str("Tapp", 2012315062, 4)) +); + +/******************************************************************** +** Solidified function: _anonymous_ +********************************************************************/ +be_local_closure(_anonymous_, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_const_class(be_class_Tapp), + }), + (be_nested_const_str("_anonymous_", 1957281476, 11)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 5]) { /* code */ + 0x58040000, // 0000 LDCONST R1 K0 + 0xB4000000, // 0001 CLASS K0 + 0x5C080200, // 0002 MOVE R2 R1 + 0x7C080000, // 0003 CALL R2 0 + 0x80040400, // 0004 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified module: tapp +********************************************************************/ +be_local_module(tapp, + "tapp", + be_nested_map(1, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_nested_key("init", 380752755, 4, -1), be_const_closure(_anonymous__closure) }, + })) +); +BE_EXPORT_VARIABLE be_define_const_native_module(tapp); +/********************************************************************/ diff --git a/lib/libesp32/Berry/default/embedded/tapp.be b/lib/libesp32/Berry/default/embedded/tapp.be new file mode 100644 index 000000000..3c3528e3a --- /dev/null +++ b/lib/libesp32/Berry/default/embedded/tapp.be @@ -0,0 +1,35 @@ +#- Tasmota apps module for Berry -# +#- -# + +var tapp_module = module("tapp") + +tapp_module.init = def (m) + + class Tapp + + def init() + tasmota.add_driver(self) + end + + def autoexec() + import path + import string + + var dir = path.listdir("/") + + for d: dir + if string.find(d, ".tapp") > 0 + print(string.format("TAP: found Tasmota App '%s'", d)) + tasmota.load(d + "#autoexec.be") + end + end + end + end + + return Tapp() # return an instance of this class +end + +# aa = autoconf_module.init(autoconf_module) +# import webserver +# webserver.on('/ac2', / -> aa.page_autoconf_mgr(), webserver.HTTP_GET) +return tapp_module diff --git a/tasmota/xdrv_52_7_berry_embedded.ino b/tasmota/xdrv_52_7_berry_embedded.ino index 4d16ced05..a51409406 100644 --- a/tasmota/xdrv_52_7_berry_embedded.ino +++ b/tasmota/xdrv_52_7_berry_embedded.ino @@ -48,6 +48,8 @@ const char berry_prog[] = "import autoconf " #endif // USE_AUTOCONF + "import tapp " + #ifdef USE_LVGL "import lv " // create the '_lvgl' global singleton diff --git a/tasmota/xdrv_52_9_berry.ino b/tasmota/xdrv_52_9_berry.ino index 751dec823..46cc5692f 100644 --- a/tasmota/xdrv_52_9_berry.ino +++ b/tasmota/xdrv_52_9_berry.ino @@ -793,6 +793,9 @@ bool Xdrv52(uint8_t function) // Run 'autoconf.preinit()' callBerryAutoconf("autoexec"); + // we generate a synthetic event `autoexec` + callBerryEventDispatcher(PSTR("autoexec"), nullptr, 0, nullptr); + BrLoad("autoexec.be"); // run autoexec.be at first tick, so we know all modules are initialized berry.autoexec_done = true; } From ab39a667ba0d116491dd3ee7dba2ccbc514c24e1 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Tue, 16 Nov 2021 07:39:55 +0100 Subject: [PATCH 040/185] serial io, tasmtimer read --- tasmota/xdrv_10_scripter.ino | 310 +++++++++++++++++++++++++++++++++-- 1 file changed, 296 insertions(+), 14 deletions(-) diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index d4b4d1134..48fe3e891 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -205,11 +205,17 @@ void alt_eeprom_readBytes(uint32_t adr, uint32_t len, uint8_t *buf) { #endif // LITTLEFS_SCRIPT_SIZE +#include #ifdef TESLA_POWERWALL #include "powerwall.h" #endif +#ifdef USE_DISPLAY_DUMP +#include +extern Renderer *renderer; +#endif + // offsets epoch readings by 1.1.2019 00:00:00 to fit into float with second resolution #ifndef EPOCH_OFFSET #define EPOCH_OFFSET 1546300800 @@ -231,7 +237,7 @@ extern FS *ufsp; #endif // USE_UFILESYS -extern "C" void homekit_main(char *, uint32_t); +extern "C" int32_t homekit_main(char *, uint32_t); #ifdef SUPPORT_MQTT_EVENT #include // Import LinkedList library @@ -434,6 +440,9 @@ struct SCRIPT_MEM { bool homekit_running = false; #endif // USE_HOMEKIT uint32_t epoch_offset = EPOCH_OFFSET; +#ifdef USE_SCRIPT_SERIAL + TasmotaSerial *sp; +#endif } glob_script_mem; @@ -3176,6 +3185,143 @@ chknext: goto exit; } #endif //USE_SML_M + +#ifdef USE_SCRIPT_SERIAL + if (!strncmp(vname, "so(", 3)) { + float rxpin, txpin, br; + lp = GetNumericArgument(lp + 3, OPER_EQU, &rxpin, gv); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp, OPER_EQU, &txpin, gv); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp, OPER_EQU, &br, gv); + SCRIPT_SKIP_SPACES + uint32_t sconfig = TS_SERIAL_8N1; + if (*lp!=')') { + // serial options, must be 3 chars 8N1, 7E2 etc + uint8_t bits = *lp++ & 0xf; + uint8_t parity = 0; + if (*lp == 'E') parity = 1; + if (*lp == 'O') parity = 2; + lp++; + uint8_t stopb = (*lp++ & 0x3) - 1; + sconfig = (bits - 5) + (parity * 8) + stopb * 4; + } + fvar= -1; + if (glob_script_mem.sp) { + fvar == -1; + } else { + if (Is_gpio_used(rxpin) || Is_gpio_used(txpin)) { + AddLog(LOG_LEVEL_INFO, PSTR("warning: pins already used")); + } + + glob_script_mem.sp = new TasmotaSerial(rxpin, txpin, 1); + if (glob_script_mem.sp) { + uint32_t config; +#ifdef ESP8266 + config = pgm_read_byte(kTasmotaSerialConfig + sconfig); +#endif // ESP8266 + +#ifdef ESP32 + config = pgm_read_dword(kTasmotaSerialConfig + sconfig); +#endif // ESP32 + fvar = glob_script_mem.sp->begin(br, config); + uint32_t savc = Settings->serial_config; + Settings->serial_config = sconfig; + AddLog(LOG_LEVEL_INFO, PSTR("Serial port set to %s %d bit/s at rx=%d tx=%d"), GetSerialConfig().c_str(), (uint32_t)br, (uint32_t)rxpin, (uint32_t)txpin); + Settings->serial_config = savc; + if (rxpin == 3 and txpin == 1) ClaimSerial(); + + } else { + fvar = -2; + } + } + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "sw(", 3)) { + char str[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp + 3, OPER_EQU, str, 0); + fvar = -1; + if (glob_script_mem.sp) { + glob_script_mem.sp->write(str, strlen(str)); + fvar = 0; + } + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "swb(", 4)) { + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); + fvar = -1; + if (glob_script_mem.sp) { + glob_script_mem.sp->write((uint8_t)fvar); + fvar = 0; + } + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "sa(", 3)) { + fvar = -1; + if (glob_script_mem.sp) { + fvar = glob_script_mem.sp->available(); + } + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "srb(", 3)) { + fvar = -1; + if (glob_script_mem.sp) { + fvar = glob_script_mem.sp->available(); + if (fvar > 0) { + fvar = glob_script_mem.sp->read(); + } + } + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "sp(", 3)) { + fvar = -1; + if (glob_script_mem.sp) { + fvar = glob_script_mem.sp->available(); + if (fvar > 0) { + fvar = glob_script_mem.sp->peek(); + } + } + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "sr(", 4)) { + char str[SCRIPT_MAXSSIZE]; + memset(str, 0, sizeof(str)); + fvar = -1; + if (glob_script_mem.sp) { + for (uint8_t index = 0; index < sizeof(str) - 1; index++) { + if (!glob_script_mem.sp->available()) { + break; + } + str[index] = glob_script_mem.sp->read(); + } + } + lp++; + len = 0; + if (sp) strlcpy(sp, str, glob_script_mem.max_ssize); + goto strexit;; + } + if (!strncmp(vname, "sc(", 3)) { + fvar = -1; + if (Script_Close_Serial()) { + fvar = 0; + } + lp+=4; + len = 0; + goto exit; + } +#endif //USE_SCRIPT_SERIAL break; case 't': if (!strncmp(vname, "time", 4)) { @@ -3280,6 +3426,21 @@ chknext: goto exit; } #endif + +#ifdef USE_TIMERS + if (!strncmp(vname, "ttget(", 6)) { + lp = GetNumericArgument(lp + 6, OPER_EQU, &fvar, gv); + SCRIPT_SKIP_SPACES + uint8_t index = fvar; + if (index < 1 || index > MAX_TIMERS) index = 1; + lp = GetNumericArgument(lp, OPER_EQU, &fvar, gv); + SCRIPT_SKIP_SPACES + fvar = get_tpars(index - 1, fvar); + lp++; + len = 0; + goto exit; + } +#endif break; case 'u': if (!strncmp(vname, "uptime", 6)) { @@ -3382,7 +3543,7 @@ chknext: goto exit; } #endif // USE_TTGO_WATCH -#if defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_LILYGO47) +#if defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_LILYGO47) || defined(USE_M5EPD47) if (!strncmp(vname, "wtch(", 5)) { lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, gv); fvar = Touch_Status(fvar); @@ -4498,6 +4659,9 @@ int16_t Run_script_sub(const char *type, int8_t tlen, struct GVARS *gv) { // set pin mode lp = GetNumericArgument(lp + 6, OPER_EQU, &fvar, 0); int8_t pinnr = fvar; + if (Is_gpio_used(pinnr)) { + AddLog(LOG_LEVEL_INFO, PSTR("warning: pins already used")); + } SCRIPT_SKIP_SPACES uint8_t mode = 0; if ((*lp=='I') || (*lp=='O') || (*lp=='P')) { @@ -5000,6 +5164,25 @@ int16_t Run_script_sub(const char *type, int8_t tlen, struct GVARS *gv) { return -1; } +#ifdef USE_SCRIPT_SERIAL +bool Script_Close_Serial() { + if (glob_script_mem.sp) { + glob_script_mem.sp->flush(); + delay(100); + delete(glob_script_mem.sp); + glob_script_mem.sp = 0; + return true; + } + return false; +} +#endif //USE_SCRIPT_SERIAL + +bool Is_gpio_used(uint8_t gpiopin) { + if ((gpiopin < nitems(TasmotaGlobal.gpio_pin)) && (TasmotaGlobal.gpio_pin[gpiopin] > 0)) { + return true; + } + return false; +} void ScripterEvery100ms(void) { static uint8_t xsns_index = 0; @@ -5440,6 +5623,8 @@ void ScriptSaveSettings(void) { SaveScript(); + } else { + AddLog(LOG_LEVEL_INFO, PSTR("script memory error")); } SaveScriptEnd(); @@ -5481,6 +5666,10 @@ void SaveScriptEnd(void) { return; } +#ifdef USE_SCRIPT_SERIAL + Script_Close_Serial(); +#endif + Run_Scripter(">B\n", 3, 0); Run_Scripter(">BS", 3, 0); @@ -6529,9 +6718,8 @@ char buff[512]; if (sflg) { #ifdef USE_DISPLAY_DUMP - -#include -extern Renderer *renderer; +//#include +//extern Renderer *renderer; // screen copy #define fileHeaderSize 14 @@ -6541,7 +6729,9 @@ extern Renderer *renderer; uint8_t *bp = renderer->framebuffer; uint8_t *lbuf = (uint8_t*)special_malloc(Settings->display_width * 3 + 2); if (!lbuf) return; - int8_t bpp = renderer->disp_bpp; + uint8_t dmflg = 0; + if (renderer->disp_bpp & 0x40) dmflg = 1; + int8_t bpp = renderer->disp_bpp & 0xbf;; uint8_t *lbp; uint8_t fileHeader[fileHeaderSize]; createBitmapFileHeader(Settings->display_height , Settings->display_width , fileHeader); @@ -6549,8 +6739,7 @@ extern Renderer *renderer; uint8_t infoHeader[infoHeaderSize]; createBitmapInfoHeader(Settings->display_height, Settings->display_width, infoHeader ); Webserver->client().write((uint8_t *)infoHeader, infoHeaderSize); - - if (bpp == -1) { + if (bpp < 0) { for (uint32_t lins = Settings->display_height - 1; lins >= 0 ; lins--) { lbp = lbuf; for (uint32_t cols = 0; cols < Settings->display_width; cols ++) { @@ -6570,16 +6759,30 @@ extern Renderer *renderer; if (bpp == 4) { for (uint32_t cols = 0; cols < Settings->display_width; cols += 2) { uint8_t pixel; - for (uint32_t cnt = 0; cnt <= 1; cnt++) { - if (cnt & 1) { - pixel = *bp >> 4; - } else { - pixel = *bp & 0xf; + if (!dmflg) { + for (uint32_t cnt = 0; cnt <= 1; cnt++) { + if (cnt & 1) { + pixel = *bp >> 4; + } else { + pixel = *bp & 0xf; + } } pixel *= 15; *--lbp = pixel; *--lbp = pixel; *--lbp = pixel; + } else { + for (uint32_t cnt = 0; cnt <= 1; cnt++) { + if (!(cnt & 1)) { + pixel = *bp >> 4; + } else { + pixel = *bp & 0xf; + } + pixel *= 15; + *--lbp = pixel; + *--lbp = pixel; + *--lbp = pixel; + } } bp++; } @@ -6601,8 +6804,8 @@ extern Renderer *renderer; bp++; } } + Webserver->client().write((const char*)lbuf, Settings->display_width * 3); } - Webserver->client().write((const char*)lbuf, Settings->display_width * 3); } if (lbuf) free(lbuf); Webserver->client().stop(); @@ -6796,6 +6999,13 @@ const char SCRIPT_MSG_SLIDER[] PROGMEM = const char SCRIPT_MSG_CHKBOX[] PROGMEM = "
"; +const char SCRIPT_MSG_PULLDOWNa[] PROGMEM = + "
"; + const char SCRIPT_MSG_TEXTINP[] PROGMEM = "
"; @@ -7098,7 +7308,43 @@ void ScriptWebShow(char mc) { uval = 1; } WSContentSend_PD(SCRIPT_MSG_CHKBOX, label, (char*)cp, uval, vname); + } else if (!strncmp(lin, "pd(", 3)) { + // pull down + char *lp = lin + 3; + char *slp = lp; + float val; + lp = GetNumericArgument(lp, OPER_EQU, &val, 0); + SCRIPT_SKIP_SPACES + char vname[16]; + ScriptGetVarname(vname, slp, sizeof(vname)); + + SCRIPT_SKIP_SPACES + char pulabel[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, pulabel, 0); + + WSContentSend_PD(SCRIPT_MSG_PULLDOWNa, vname, pulabel, 1, vname, vname); + + // get pu labels + uint8_t index = 1; + while (*lp) { + SCRIPT_SKIP_SPACES + lp = GetStringArgument(lp, OPER_EQU, pulabel, 0); + char *cp; + if (val == index) { + cp = (char*)"selected"; + } else { + cp = (char*)""; + } + WSContentSend_PD(SCRIPT_MSG_PULLDOWNb, cp, index, pulabel); + SCRIPT_SKIP_SPACES + if (*lp == ')') { + lp++; + break; + } + index++; + } + WSContentSend_PD(SCRIPT_MSG_PULLDOWNc); } else if (!strncmp(lin, "bu(", 3)) { char *lp = lin + 3; uint8_t bcnt = 0; @@ -8295,6 +8541,42 @@ void lvgl_setup(void) { #endif // USE_LVGL + +#ifdef USE_TIMERS +int32_t get_tpars(uint32_t index, uint32_t sel) { +int32_t retval = 0; + switch (sel) { + case 0: + retval = Settings->timer[index].time; + break; + case 1: + //retval = Settings->timer[index].window; + retval = timer_window[index]; + break; + case 2: + retval = Settings->timer[index].repeat; + break; + case 3: + retval = Settings->timer[index].days; + break; + case 4: + retval = Settings->timer[index].device; + break; + case 5: + retval = Settings->timer[index].power; + break; + case 6: + retval = Settings->timer[index].mode; + break; + case 7: + retval = Settings->timer[index].arm; + break; + } + return retval; +} + +#endif + /*********************************************************************************************\ * Interface \*********************************************************************************************/ From d7dad7a8834d6c52f590031221bb42f51ab095f7 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Tue, 16 Nov 2021 07:41:02 +0100 Subject: [PATCH 041/185] get number of open sockets for debugging --- tasmota/homekit.c | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/tasmota/homekit.c b/tasmota/homekit.c index 92e19543c..55d71c239 100755 --- a/tasmota/homekit.c +++ b/tasmota/homekit.c @@ -38,7 +38,7 @@ #include #include #include - +#include #include @@ -703,9 +703,9 @@ nextline: #define HK_PASSCODE "111-11-111" int hap_loop_stop(void); +int32_t homekit_pars(uint32_t sel); - -void homekit_main(char *desc, uint32_t flag ) { +int32_t homekit_main(char *desc, uint32_t flag ) { if (desc) { char *cp = desc; cp += 2; @@ -724,7 +724,7 @@ void homekit_main(char *desc, uint32_t flag ) { } if (*cp != '\n') { printf("init error\n"); - return; + return -1; } cp++; hk_desc = cp; @@ -736,17 +736,44 @@ void homekit_main(char *desc, uint32_t flag ) { hap_loop_stop(); // is just the folder in wrapper hap_platfrom_keystore_erase_partition(hap_platform_keystore_get_nvs_partition_name()); + } else if (flag < 3) { + return homekit_pars(flag); } else { hap_loop_stop(); } - return; + + return 0; } - if (!hk_desc) return; + if (!hk_desc) return -2; /* Create the application thread */ xTaskCreate(smart_outlet_thread_entry, SMART_OUTLET_TASK_NAME, SMART_OUTLET_TASK_STACKSIZE, NULL, SMART_OUTLET_TASK_PRIORITY, NULL); + return 0; +} + +#include + +int32_t homekit_pars(uint32_t sel) { + + if (sel == 0) { + // return CONFIG_LWIP_MAX_SOCKETS; + return MEMP_NUM_NETCONN; + } else if (sel == 1) { + return LWIP_SOCKET_OFFSET; + } else { + struct sockaddr name; + socklen_t len = sizeof(name); + uint8_t open_socs = 0; + for (uint32_t cnt = 0; cnt < CONFIG_LWIP_MAX_SOCKETS; cnt++) { + //if (!getsockname(cnt, &name, &len)) { + if (!getpeername(LWIP_SOCKET_OFFSET + cnt, &name, &len)) { + open_socs++; + } + } + return open_socs; + } } #endif // ESP32 From 1278682182b7b0bdf82acb8f168231d8166fe71f Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Tue, 16 Nov 2021 08:03:15 +0100 Subject: [PATCH 042/185] epaper area calls --- .../Display_Renderer-gemu-1.0/src/renderer.cpp | 18 ++++++++++++++++++ .../Display_Renderer-gemu-1.0/src/renderer.h | 4 ++++ 2 files changed, 22 insertions(+) diff --git a/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.cpp b/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.cpp index fb223680b..e09ab71a8 100644 --- a/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.cpp +++ b/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.cpp @@ -633,6 +633,12 @@ LVGL_PARAMS *Renderer::lvgl_pars(void) { return &lvgl_param; } +void Renderer::ep_update_mode(uint8_t mode) { +} + +void Renderer::ep_update_area(uint16_t xp, uint16_t yp, uint16_t width, uint16_t height, uint8_t mode) { +} + // #ifndef USE_DISPLAY_LVGL_ONLY @@ -642,6 +648,18 @@ void VButton::xdrawButton(bool inverted) { wr_redir=0; } +void VButton::xinitButtonUL(Renderer *renderer, int16_t gxp, int16_t gyp, uint16_t gxs, uint16_t gys, uint16_t outline,\ + uint16_t fill, uint16_t textcolor , char *label, uint8_t textsize) { + + initButtonUL(renderer, gxp, gyp, gxs, gys, outline, fill, textcolor, label, textsize); + + spars.xp = gxp; + spars.yp = gyp; + spars.xs = gxs; + spars.ys = gys; + +} + boolean VButton::didhit(int16_t x, int16_t y) { return ((x >= spars.xp) && (x < (int16_t) (spars.xp + spars.xs)) && (y >= spars.yp) && (y < (int16_t) (spars.yp + spars.ys))); diff --git a/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.h b/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.h index 49f4d7b5e..3e3304fbb 100644 --- a/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.h +++ b/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.h @@ -88,6 +88,8 @@ public: virtual void Splash(void); virtual char *devname(void); virtual LVGL_PARAMS *lvgl_pars(void); + virtual void ep_update_mode(uint8_t mode); + virtual void ep_update_area(uint16_t xp, uint16_t yp, uint16_t width, uint16_t height, uint8_t mode); void setDrawMode(uint8_t mode); uint8_t drawmode; @@ -144,6 +146,8 @@ class VButton : public Adafruit_GFX_Button { boolean didhit(int16_t x, int16_t y); uint16_t UpdateSlider(int16_t x, int16_t y); void SliderInit(Renderer *rend, uint16_t xp, uint16_t yp, uint16_t xs, uint16_t ys, uint16_t nelem, uint16_t bgcol, uint16_t frcol, uint16_t barcol); + void xinitButtonUL(Renderer *renderer, int16_t gxp, int16_t gyp, uint16_t gxs, uint16_t gys, uint16_t outline,\ + uint16_t fill, uint16_t textcolor , char *label, uint8_t textsize); }; // #endif // USE_DISPLAY_LVGL_ONLY From 3885a19b57990f787580f6da687d88eb4eedf90c Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Tue, 16 Nov 2021 08:09:04 +0100 Subject: [PATCH 043/185] enable all pins for cs and dc --- lib/lib_display/UDisplay/uDisplay.cpp | 1 + lib/lib_display/UDisplay/uDisplay.h | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/lib_display/UDisplay/uDisplay.cpp b/lib/lib_display/UDisplay/uDisplay.cpp index aa2dae903..6f48d5796 100755 --- a/lib/lib_display/UDisplay/uDisplay.cpp +++ b/lib/lib_display/UDisplay/uDisplay.cpp @@ -343,6 +343,7 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) { Serial.printf("SPED: %d\n", spi_speed*1000000); Serial.printf("Pixels: %d\n", col_mode); Serial.printf("SaMode: %d\n", sa_mode); + Serial.printf("DMA-Mode: %d\n", lvgl_param.use_dma); Serial.printf("opts: %02x,%02x,%02x\n", saw_3, dim_op, startline); diff --git a/lib/lib_display/UDisplay/uDisplay.h b/lib/lib_display/UDisplay/uDisplay.h index 8ce012bf5..3dbc5aed7 100755 --- a/lib/lib_display/UDisplay/uDisplay.h +++ b/lib/lib_display/UDisplay/uDisplay.h @@ -68,10 +68,12 @@ enum uColorType { uCOLOR_BW, uCOLOR_COLOR }; #define SPI_BEGIN_TRANSACTION if (spi_nr <= 2) beginTransaction(spiSettings); #define SPI_END_TRANSACTION if (spi_nr <= 2) endTransaction(); -#define SPI_CS_LOW if (spi_cs >= 0) GPIO_CLR(spi_cs); -#define SPI_CS_HIGH if (spi_cs >= 0) GPIO_SET(spi_cs); -#define SPI_DC_LOW if (spi_dc >= 0) GPIO_CLR(spi_dc); -#define SPI_DC_HIGH if (spi_dc >= 0) GPIO_SET(spi_dc); + +#define SPI_CS_LOW if (spi_cs >= 0) GPIO_CLR_SLOW(spi_cs); +#define SPI_CS_HIGH if (spi_cs >= 0) GPIO_SET_SLOW(spi_cs); +#define SPI_DC_LOW if (spi_dc >= 0) GPIO_CLR_SLOW(spi_dc); +#define SPI_DC_HIGH if (spi_dc >= 0) GPIO_SET_SLOW(spi_dc); + #define ESP32_PWM_CHANNEL 1 From a35846769d9dba87002a618e4a3bfd296af34b19 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Tue, 16 Nov 2021 08:12:23 +0100 Subject: [PATCH 044/185] epaper area update, fix graph overflow --- tasmota/xdrv_13_display.ino | 41 ++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/tasmota/xdrv_13_display.ino b/tasmota/xdrv_13_display.ino index bcf545bc5..636d0e1ce 100755 --- a/tasmota/xdrv_13_display.ino +++ b/tasmota/xdrv_13_display.ino @@ -701,6 +701,12 @@ void DisplayText(void) if (renderer) renderer->fillCircle(disp_xpos, disp_ypos, temp, fg_color); //else DisplayDrawFilledCircle(disp_xpos, disp_ypos, temp, fg_color); break; + case 'm': + // epaper draw mode currently only for 4,7 inch displays + var = atoiv(cp, &temp); + cp += var; + if (renderer) renderer->ep_update_mode(temp); + break; case 'r': // rectangle var = atoiv(cp, &temp); @@ -723,7 +729,27 @@ void DisplayText(void) break; case 'u': // rounded rectangle - { int16_t rad; + { int16_t rad, xp, yp, width, height; + if (*cp == 'p') { + // update epaper display + cp++; + var = atoiv(cp, &xp); + cp += var; + cp++; + var = atoiv(cp, &yp); + cp += var; + cp++; + var = atoiv(cp, &width); + cp += var; + cp++; + var = atoiv(cp, &height); + cp += var; + cp++; + var = atoiv(cp, &temp); + cp += var; + if (renderer) renderer->ep_update_area(xp, yp, width, height, temp); + break; + } var = atoiv(cp, &temp); cp += var; cp++; @@ -1100,7 +1126,7 @@ extern FS *ffsp; if (buttons[num]) { if (!sbt) { buttons[num]->vpower.slider = 0; - buttons[num]->initButtonUL(renderer, gxp, gyp, gxs, gys, GetColorFromIndex(outline),\ + buttons[num]->xinitButtonUL(renderer, gxp, gyp, gxs, gys, GetColorFromIndex(outline),\ GetColorFromIndex(fill), GetColorFromIndex(textcolor), bbuff, textsize); if (!bflags) { // power button @@ -1969,6 +1995,7 @@ void ApplyDisplayDimmer(void) { // still call Berry virtual display in case it is not managed entirely by renderer Xdsp18(FUNC_DISPLAY_DIM); #endif // USE_BERRY + } else { XdspCall(FUNC_DISPLAY_DIM); } @@ -2631,7 +2658,11 @@ void Restore_graph(uint8_t num, char *path) { if (count<=4) { if (count==0) gp->xcnt=atoi(vbuff); } else { - gp->values[count-5]=atoi(vbuff); + uint8_t yval = atoi(vbuff); + if (yval >= gp->ys) { + yval = gp->ys - 1; + } + gp->values[count-5] = yval; } } fp.close(); @@ -2735,9 +2766,9 @@ void AddValue(uint8_t num,float fval) { // decimation option if (gp->decimation<0) { if (gp->dcnt>=-gp->decimation) { - gp->dcnt=0; // calc average - val=gp->summ/-gp->decimation; + val=gp->summ/gp->dcnt; + gp->dcnt=0; gp->summ=0; // add to graph AddGraph(num,val); From a2c34214e0e312bfa75b9dbb50b6d351f8cdafc1 Mon Sep 17 00:00:00 2001 From: stefanbode Date: Tue, 16 Nov 2021 13:02:36 +0100 Subject: [PATCH 045/185] Update xdrv_27_shutter.ino --- tasmota/xdrv_27_shutter.ino | 91 ++++++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 36 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index fcdff233c..7143c1170 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -59,7 +59,7 @@ const char kShutterCommands[] PROGMEM = D_PRFX_SHUTTER "|" D_CMND_SHUTTER_SETHALFWAY "|" D_CMND_SHUTTER_SETCLOSE "|" D_CMND_SHUTTER_SETOPEN "|" D_CMND_SHUTTER_INVERT "|" D_CMND_SHUTTER_CLIBRATION "|" D_CMND_SHUTTER_MOTORDELAY "|" D_CMND_SHUTTER_FREQUENCY "|" D_CMND_SHUTTER_BUTTON "|" D_CMND_SHUTTER_LOCK "|" D_CMND_SHUTTER_ENABLEENDSTOPTIME "|" D_CMND_SHUTTER_INVERTWEBBUTTONS "|" D_CMND_SHUTTER_STOPOPEN "|" D_CMND_SHUTTER_STOPCLOSE "|" D_CMND_SHUTTER_STOPTOGGLE "|" D_CMND_SHUTTER_STOPTOGGLEDIR "|" D_CMND_SHUTTER_STOPPOSITION "|" D_CMND_SHUTTER_INCDEC "|" - D_CMND_SHUTTER_UNITTEST "|" D_CMND_SHUTTER_TILTCONFIG "|" D_CMND_SHUTTER_SETTILT "|"; + D_CMND_SHUTTER_UNITTEST "|" D_CMND_SHUTTER_TILTCONFIG "|" D_CMND_SHUTTER_SETTILT "|" D_CMND_SHUTTER_TILTINCDEC "|"; void (* const ShutterCommand[])(void) PROGMEM = { &CmndShutterOpen, &CmndShutterClose, &CmndShutterToggle, &CmndShutterToggleDir, &CmndShutterStop, &CmndShutterPosition, @@ -67,7 +67,7 @@ void (* const ShutterCommand[])(void) PROGMEM = { &CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterSetOpen, &CmndShutterInvert, &CmndShutterCalibration , &CmndShutterMotorDelay, &CmndShutterFrequency, &CmndShutterButton, &CmndShutterLock, &CmndShutterEnableEndStopTime, &CmndShutterInvertWebButtons, &CmndShutterStopOpen, &CmndShutterStopClose, &CmndShutterStopToggle, &CmndShutterStopToggleDir, &CmndShutterStopPosition, &CmndShutterIncDec, - &CmndShutterUnitTest,&CmndShutterTiltConfig,&CmndShutterSetTilt}; + &CmndShutterUnitTest,&CmndShutterTiltConfig,&CmndShutterSetTilt,&CmndShutterTiltIncDec}; const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"Direction\":%d,\"Target\":%d,\"Tilt\":%d}"; const char JSON_SHUTTER_BUTTON[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Button%d\":%d}"; @@ -102,7 +102,7 @@ struct SHUTTER { uint16_t venetian_delay = 0; // Delay in steps before venetian shutter start physical moving. Based on tilt position uint16_t min_realPositionChange = 0; // minimum change of the position before the shutter operates. different for PWM and time based operations uint16_t min_TiltChange = 0; // minimum change of the tilt before the shutter operates. different for PWM and time based operations - uint16_t missed_steps =0; + uint16_t last_reported_time =0; } Shutter[MAX_SHUTTERS]; struct SHUTTERGLOBAL { @@ -530,11 +530,12 @@ void ShutterUpdatePosition(void) XdrvRulesProcess(0); ShutterGlobal.start_reported = 1; } + int32_t deltatime = Shutter[i].time-Shutter[i].last_reported_time; + Shutter[i].last_reported_time = Shutter[i].time+1; AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Time %d(%d), cStop %d, cVelo %d, mVelo %d, aVelo %d, mRun %d, aPos %d, aPos2 %d, nStop %d, Trgt %d, mVelo %d, Dir %d, Tilt %d, TrgtTilt: %d, Tiltmove: %d"), - Shutter[i].time, Shutter[i].time-Shutter[i].missed_steps,current_stop_way, current_pwm_velocity, velocity_max, Shutter[i].accelerator, min_runtime_ms, current_real_position,Shutter[i].real_position, + Shutter[i].time, deltatime, current_stop_way, current_pwm_velocity, velocity_max, Shutter[i].accelerator, min_runtime_ms, current_real_position,Shutter[i].real_position, next_possible_stop_position, Shutter[i].target_position, velocity_change_per_step_max, Shutter[i].direction,Shutter[i].tilt_real_pos, Shutter[i].tilt_target_pos, Shutter[i].tiltmoving); - Shutter[i].missed_steps = Shutter[i].time+1; if ( ((Shutter[i].real_position * Shutter[i].direction >= Shutter[i].target_position * Shutter[i].direction && Shutter[i].tiltmoving==0) || ((int16_t)Shutter[i].tilt_real_pos * Shutter[i].direction * Shutter[i].tilt_config[2] >= (int16_t)Shutter[i].tilt_target_pos * Shutter[i].direction * Shutter[i].tilt_config[2] && Shutter[i].tiltmoving==1)) || (ShutterGlobal.position_mode == SHT_COUNTER && Shutter[i].accelerator <0 && Shutter[i].pwm_velocity+Shutter[i].accelerator 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) { - if (XdrvMailbox.payload != -99 ) { - Shutter[XdrvMailbox.index -1].tilt_target_pos = tmin(tmax(XdrvMailbox.payload, Shutter[XdrvMailbox.index -1].tilt_config[0]), Shutter[XdrvMailbox.index -1].tilt_config[1]); - XdrvMailbox.payload = -99; - } - if ((XdrvMailbox.data_len > 1) && (XdrvMailbox.payload <= 0)) { - if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_OPEN) ) { - Shutter[XdrvMailbox.index -1].tilt_target_pos = Shutter[XdrvMailbox.index -1].tilt_config[3]; // open position - XdrvMailbox.payload = -99; - } - if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_CLOSE) ) { - Shutter[XdrvMailbox.index -1].tilt_target_pos = Shutter[XdrvMailbox.index -1].tilt_config[4]; // close position - XdrvMailbox.payload = -99; - } - } - } - XdrvMailbox.data[0] = '\0'; - ResponseCmndNumber(Shutter[XdrvMailbox.index -1].tilt_target_pos); - Shutter[XdrvMailbox.index -1].tiltmoving = 1; - CmndShutterPosition(); -} - void CmndShutterFrequency(void) { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 20000)) { @@ -1569,7 +1546,8 @@ void CmndShutterCalibration(void) } } -void ShutterOptionsSetHelper(uint16_t option){ +void ShutterOptionsSetHelper(uint16_t option) +{ if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) { if (XdrvMailbox.payload == 0) { Settings->shutter_options[XdrvMailbox.index -1] &= ~(option); @@ -1580,23 +1558,52 @@ void ShutterOptionsSetHelper(uint16_t option){ } } -void CmndShutterInvert(void) { +void CmndShutterInvert(void) +{ ShutterOptionsSetHelper(1); } -void CmndShutterLock(void) { +void CmndShutterLock(void) +{ ShutterOptionsSetHelper(2); } -void CmndShutterEnableEndStopTime(void) { +void CmndShutterEnableEndStopTime(void) +{ ShutterOptionsSetHelper(4); } -void CmndShutterInvertWebButtons(void) { +void CmndShutterInvertWebButtons(void) +{ ShutterOptionsSetHelper(8); } -void CmndShutterTiltConfig(void) { +void CmndShutterSetTilt(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) { + if (XdrvMailbox.payload != -99 ) { + Shutter[XdrvMailbox.index -1].tilt_target_pos = tmin(tmax(XdrvMailbox.payload, Shutter[XdrvMailbox.index -1].tilt_config[0]), Shutter[XdrvMailbox.index -1].tilt_config[1]); + XdrvMailbox.payload = -99; + } + if ((XdrvMailbox.data_len > 1) && (XdrvMailbox.payload <= 0)) { + if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_OPEN) ) { + Shutter[XdrvMailbox.index -1].tilt_target_pos = Shutter[XdrvMailbox.index -1].tilt_config[3]; // open position + XdrvMailbox.payload = -99; + } + if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_CLOSE) ) { + Shutter[XdrvMailbox.index -1].tilt_target_pos = Shutter[XdrvMailbox.index -1].tilt_config[4]; // close position + XdrvMailbox.payload = -99; + } + } + } + XdrvMailbox.data[0] = '\0'; + ResponseCmndNumber(Shutter[XdrvMailbox.index -1].tilt_target_pos); + Shutter[XdrvMailbox.index -1].tiltmoving = 1; + CmndShutterPosition(); +} + +void CmndShutterTiltConfig(void) +{ if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) { if (XdrvMailbox.data_len > 0) { uint8_t i = 0; @@ -1618,6 +1625,18 @@ void CmndShutterTiltConfig(void) { } } +void CmndShutterTiltIncDec(void) +{ + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Change in: payload %s (%d), payload %d, idx %d, src %d"), XdrvMailbox.data , XdrvMailbox.data_len, XdrvMailbox.payload , XdrvMailbox.index, TasmotaGlobal.last_source ); + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) { + if (XdrvMailbox.data_len > 0) { + XdrvMailbox.payload = Shutter[XdrvMailbox.index -1].tilt_target_pos+XdrvMailbox.payload; + CmndShutterSetTilt(); + } + } + ResponseCmndNumber(Shutter[XdrvMailbox.index -1].tilt_target_pos); +} + /*********************************************************************************************\ * Interface \*********************************************************************************************/ From 65be8e6b59e06cd154d098511f9e5aa8a841da8f Mon Sep 17 00:00:00 2001 From: stefanbode Date: Tue, 16 Nov 2021 13:04:02 +0100 Subject: [PATCH 046/185] Introduced: shuttertiltchange shuttertiltchange allows a change of the tilt. Most likely used with buttons --- tasmota/i18n.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tasmota/i18n.h b/tasmota/i18n.h index c08703e0f..1b8115d28 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -694,6 +694,7 @@ #define D_CMND_SHUTTER_UNITTEST "UnitTest" #define D_CMND_SHUTTER_TILTCONFIG "TiltConfig" #define D_CMND_SHUTTER_SETTILT "Tilt" +#define D_CMND_SHUTTER_TILTINCDEC "TiltChange" // Commands xdrv_32_hotplug.ino #define D_CMND_HOTPLUG "HotPlug" From 834244d2e10dda31ddacef4b96b2d599618be15d Mon Sep 17 00:00:00 2001 From: stefanbode Date: Tue, 16 Nov 2021 13:46:22 +0100 Subject: [PATCH 047/185] Update xdrv_27_shutter.ino --- tasmota/xdrv_27_shutter.ino | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 7143c1170..110740746 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -47,6 +47,7 @@ int32_t current_stop_way = 0; int32_t next_possible_stop_position = 0; int32_t current_real_position = 0; int32_t current_pwm_velocity = 0; +int8_t savedata_original = 0; const uint8_t MAX_MODES = 7; enum Shutterposition_mode {SHT_UNDEF, SHT_TIME, SHT_TIME_UP_DOWN, SHT_TIME_GARAGE, SHT_COUNTER, SHT_PWM_VALUE, SHT_PWM_TIME,}; @@ -516,6 +517,8 @@ void ShutterPowerOff(uint8_t i) ExecuteCommand(scmnd, SRC_BUTTON); break; } + Settings->save_data = savedata_original; + TasmotaGlobal.save_data_counter = Settings->save_data; delay(MOTOR_STOP_TIME); } @@ -601,7 +604,7 @@ void ShutterAllowPreStartProcedure(uint8_t i) void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) { - AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: dir %d, delta1 %d, delta2 %d"),direction, (Shutter[i].open_max - Shutter[i].real_position) / Shutter[i].close_velocity, Shutter[i].real_position / Shutter[i].close_velocity); + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: dir %d, delta1 %d, delta2 %d"),direction, (Shutter[i].open_max - Shutter[i].real_position) / Shutter[i].close_velocity, Shutter[i].real_position / Shutter[i].close_velocity); if ( ( ( (1 == direction) && ((Shutter[i].open_max - Shutter[i].real_position) <= Shutter[i].min_realPositionChange)) || ( (-1 == direction) && (Shutter[i].real_position <= Shutter[i].min_realPositionChange)) ) && abs(Shutter[i].tilt_real_pos-Shutter[i].tilt_target_pos) <= Shutter[i].min_TiltChange) { @@ -617,12 +620,19 @@ void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) break; #endif } + Shutter[i].accelerator = ShutterGlobal.open_velocity_max / (Shutter[i].motordelay>0 ? Shutter[i].motordelay : 1); Shutter[i].target_position = target_pos; Shutter[i].start_position = Shutter[i].real_position; TasmotaGlobal.rules_flag.shutter_moving = 1; ShutterAllowPreStartProcedure(i); Shutter[i].time = 0; + + // avoid file system writes during move to minimize missing steps + savedata_original = Settings->save_data; + Settings->save_data = 0; // will be restored after movement + TasmotaGlobal.save_data_counter = Settings->save_data; + Shutter[i].direction = direction; Shutter[i].last_reported_time = 1; ShutterGlobal.skip_relay_change = 0; @@ -633,11 +643,12 @@ void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) if (Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0] != 0) { Shutter[i].venetian_delay = (Shutter[i].direction > 0 ? Shutter[i].tilt_config[1]-Shutter[i].tilt_real_pos : Shutter[i].tilt_real_pos-Shutter[i].tilt_config[0]) * Shutter[i].tilt_config[2] / (Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0]); //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: real %d, start %d, counter %d,freq_max %d, dir %d, freq %d"),Shutter[i].real_position, Shutter[i].start_position ,RtcSettings.pulse_counter[i],ShutterGlobal.open_velocity_max , Shutter[i].direction ,ShutterGlobal.open_velocity_max ); - AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: %d VenetianDelay: %d, Pos: %d, Dir: %d, Delta: %d, Durat: %d, Start: %d, Target: %d"), - i, Shutter[i].venetian_delay, Shutter[i].tilt_real_pos,Shutter[i].direction,(Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0]), Shutter[i].tilt_config[2],Shutter[i].tilt_start_pos,Shutter[i].tilt_target_pos); + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: VenetianDelay: %d, Pos: %d, Dir: %d, Delta: %d, Dur: %d, StartP: %d, TgtP: %d"), + Shutter[i].venetian_delay, Shutter[i].tilt_real_pos,Shutter[i].direction,(Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0]), Shutter[i].tilt_config[2],Shutter[i].tilt_start_pos,Shutter[i].tilt_target_pos); } } - AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Start shtr%d from %d to %d in direction %d"), i, Shutter[i].start_position, Shutter[i].target_position, Shutter[i].direction); + //AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Start shtr%d from %d to %d in dir: %d"), i, Shutter[i].start_position, Shutter[i].target_position, direction); + Shutter[i].direction = direction; // Last action. This causes RTC to start. } int32_t ShutterCalculatePosition(uint32_t i) @@ -957,7 +968,7 @@ void ShutterSetPosition(uint32_t device, uint32_t position) void ShutterToggle(bool dir) { - AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Payload toggle: %d, i %d, dir %d, lastdir %d"), XdrvMailbox.payload, XdrvMailbox.index, dir, Shutter[XdrvMailbox.index-1].lastdirection); + AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Toggle: %d, i %d, dir %d, lastdir %d"), XdrvMailbox.payload, XdrvMailbox.index, dir, Shutter[XdrvMailbox.index-1].lastdirection); if ((1 == XdrvMailbox.index) && (XdrvMailbox.payload != -99)) { XdrvMailbox.index = XdrvMailbox.payload; } From 79979a27fb5c3ef8ca5c29b5f510d7d4734006af Mon Sep 17 00:00:00 2001 From: stefanbode Date: Tue, 16 Nov 2021 14:00:49 +0100 Subject: [PATCH 048/185] Update xdrv_27_shutter.ino --- tasmota/xdrv_27_shutter.ino | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 110740746..7d988e193 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -626,15 +626,12 @@ void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) Shutter[i].start_position = Shutter[i].real_position; TasmotaGlobal.rules_flag.shutter_moving = 1; ShutterAllowPreStartProcedure(i); - Shutter[i].time = 0; + Shutter[i].time = Shutter[i].last_reported_time = 0; // avoid file system writes during move to minimize missing steps savedata_original = Settings->save_data; Settings->save_data = 0; // will be restored after movement TasmotaGlobal.save_data_counter = Settings->save_data; - - Shutter[i].direction = direction; - Shutter[i].last_reported_time = 1; ShutterGlobal.skip_relay_change = 0; TasmotaGlobal.rules_flag.shutter_moved = 0; ShutterGlobal.start_reported = 0; From 6e120aa0b83f20adfa62418eefa630c8547ecf97 Mon Sep 17 00:00:00 2001 From: stefanbode Date: Tue, 16 Nov 2021 15:28:14 +0100 Subject: [PATCH 049/185] Update xdrv_27_shutter.ino --- tasmota/xdrv_27_shutter.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 7d988e193..e9200c0b6 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -638,10 +638,10 @@ void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) Shutter[i].tilt_real_pos = tmax(tmin(Shutter[i].tilt_real_pos,Shutter[i].tilt_config[1]),Shutter[i].tilt_config[0]); Shutter[i].tilt_start_pos = Shutter[i].tilt_real_pos; if (Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0] != 0) { - Shutter[i].venetian_delay = (Shutter[i].direction > 0 ? Shutter[i].tilt_config[1]-Shutter[i].tilt_real_pos : Shutter[i].tilt_real_pos-Shutter[i].tilt_config[0]) * Shutter[i].tilt_config[2] / (Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0]); - //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: real %d, start %d, counter %d,freq_max %d, dir %d, freq %d"),Shutter[i].real_position, Shutter[i].start_position ,RtcSettings.pulse_counter[i],ShutterGlobal.open_velocity_max , Shutter[i].direction ,ShutterGlobal.open_velocity_max ); + Shutter[i].venetian_delay = (direction > 0 ? Shutter[i].tilt_config[1]-Shutter[i].tilt_real_pos : Shutter[i].tilt_real_pos-Shutter[i].tilt_config[0]) * Shutter[i].tilt_config[2] / (Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0]); + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: real %d, start %d, counter %d,freq_max %d, dir %d, freq %d"),Shutter[i].real_position, Shutter[i].start_position ,RtcSettings.pulse_counter[i],ShutterGlobal.open_velocity_max , direction ,ShutterGlobal.open_velocity_max ); AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: VenetianDelay: %d, Pos: %d, Dir: %d, Delta: %d, Dur: %d, StartP: %d, TgtP: %d"), - Shutter[i].venetian_delay, Shutter[i].tilt_real_pos,Shutter[i].direction,(Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0]), Shutter[i].tilt_config[2],Shutter[i].tilt_start_pos,Shutter[i].tilt_target_pos); + Shutter[i].venetian_delay, Shutter[i].tilt_real_pos,direction,(Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0]), Shutter[i].tilt_config[2],Shutter[i].tilt_start_pos,Shutter[i].tilt_target_pos); } } //AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Start shtr%d from %d to %d in dir: %d"), i, Shutter[i].start_position, Shutter[i].target_position, direction); From c8e03e2d3b81badc63067430b2565acff4bcab9e Mon Sep 17 00:00:00 2001 From: stefanbode Date: Tue, 16 Nov 2021 17:05:45 +0100 Subject: [PATCH 050/185] Update xdrv_27_shutter.ino --- tasmota/xdrv_27_shutter.ino | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index e9200c0b6..9fcfa74d9 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -328,7 +328,8 @@ void ShutterInit(void) for (uint8_t k=0; k<5; k++) { Shutter[i].tilt_config[k] = Settings->shutter_tilt_config[k][i]; } - Shutter[i].tilt_real_pos = Settings->shutter_tilt_pos[i]; + Shutter[i].tilt_target_pos = Shutter[i].tilt_real_pos = Settings->shutter_tilt_pos[i]; + Shutter[i].tilt_velocity = Shutter[i].tilt_config[2] > 0 ? ((Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0])/Shutter[i].tilt_config[2])+1 : 1; Shutter[i].close_velocity_max = ShutterGlobal.open_velocity_max*Shutter[i].open_time / Shutter[i].close_time; @@ -553,7 +554,8 @@ void ShutterUpdatePosition(void) // manage venetian blinds Shutter[i].tilt_target_pos = Settings->shutter_position[i] == 0 ? Shutter[i].tilt_config[0] : Shutter[i].tilt_target_pos; Shutter[i].tilt_target_pos = Settings->shutter_position[i] == 100 ? Shutter[i].tilt_config[1] : Shutter[i].tilt_target_pos; - if (abs(Shutter[i].tilt_real_pos - Shutter[i].tilt_target_pos) > Shutter[i].min_TiltChange) { + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Pre: Tilt not match %d -> %d, moving: %d"),Shutter[i].tilt_real_pos,Shutter[i].tilt_target_pos,Shutter[i].tiltmoving); + if (abs(Shutter[i].tilt_real_pos - Shutter[i].tilt_target_pos) > Shutter[i].min_TiltChange && Shutter[i].tiltmoving == 0) { AddLog(LOG_LEVEL_INFO, PSTR("SHT: Tilt not match %d -> %d"),Shutter[i].tilt_real_pos,Shutter[i].tilt_target_pos); XdrvMailbox.payload = -99; XdrvMailbox.index = i+1; From 5e799716a7275807c4d0e3ccc220faf1acf05b1e Mon Sep 17 00:00:00 2001 From: stefanbode Date: Tue, 16 Nov 2021 20:07:41 +0100 Subject: [PATCH 051/185] Update xdrv_27_shutter.ino --- tasmota/xdrv_27_shutter.ino | 91 ++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 42 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 9fcfa74d9..609dd7628 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -125,6 +125,7 @@ void ShutterLogPos(uint32_t i) AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d Real %d, Start %d, Stop %d, Dir %d, Delay %d, Rtc %s [s], Freq %d, PWM %d, Tilt %d"), i+1, Shutter[i].real_position, Shutter[i].start_position, Shutter[i].target_position, Shutter[i].direction, Shutter[i].motordelay, stemp2, Shutter[i].pwm_velocity, Shutter[i].pwm_value,Shutter[i].tilt_real_pos); + yield(); } void ExecuteCommandPowerShutter(uint32_t device, uint32_t state, uint32_t source) @@ -365,7 +366,7 @@ void ShutterInit(void) void ShutterReportPosition(bool always, uint32_t index) { Response_P(PSTR("{")); - TasmotaGlobal.rules_flag.shutter_moving = 0; + //TasmotaGlobal.rules_flag.shutter_moving = 0; uint32_t i = 0; uint32_t n = TasmotaGlobal.shutters_present; if( index != MAX_SHUTTERS) { @@ -376,7 +377,7 @@ void ShutterReportPosition(bool always, uint32_t index) //AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d Real Pos %d"), i+1,Shutter[i].real_position); uint32_t position = ShutterRealToPercentPosition(Shutter[i].real_position, i); if (Shutter[i].direction != 0) { - TasmotaGlobal.rules_flag.shutter_moving = 1; + //TasmotaGlobal.rules_flag.shutter_moving = 1; ShutterLogPos(i); } if (i && index == MAX_SHUTTERS) { ResponseAppend_P(PSTR(",")); } @@ -479,6 +480,7 @@ void ShutterPowerOff(uint8_t i) if (Shutter[i].direction !=0) { Shutter[i].direction = 0; } + TasmotaGlobal.rules_flag.shutter_moving = 0; switch (Shutter[i].switch_mode) { case SHT_SWITCH: if ((1 << (Settings->shutter_startrelay[i]-1)) & TasmotaGlobal.power) { @@ -535,46 +537,48 @@ void ShutterUpdatePosition(void) ShutterGlobal.start_reported = 1; } int32_t deltatime = Shutter[i].time-Shutter[i].last_reported_time; - Shutter[i].last_reported_time = Shutter[i].time+1; - AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Time %d(%d), cStop %d, cVelo %d, mVelo %d, aVelo %d, mRun %d, aPos %d, aPos2 %d, nStop %d, Trgt %d, mVelo %d, Dir %d, Tilt %d, TrgtTilt: %d, Tiltmove: %d"), - Shutter[i].time, deltatime, current_stop_way, current_pwm_velocity, velocity_max, Shutter[i].accelerator, min_runtime_ms, current_real_position,Shutter[i].real_position, - next_possible_stop_position, Shutter[i].target_position, velocity_change_per_step_max, Shutter[i].direction,Shutter[i].tilt_real_pos, Shutter[i].tilt_target_pos, - Shutter[i].tiltmoving); - if ( ((Shutter[i].real_position * Shutter[i].direction >= Shutter[i].target_position * Shutter[i].direction && Shutter[i].tiltmoving==0) || - ((int16_t)Shutter[i].tilt_real_pos * Shutter[i].direction * Shutter[i].tilt_config[2] >= (int16_t)Shutter[i].tilt_target_pos * Shutter[i].direction * Shutter[i].tilt_config[2] && Shutter[i].tiltmoving==1)) - || (ShutterGlobal.position_mode == SHT_COUNTER && Shutter[i].accelerator <0 && Shutter[i].pwm_velocity+Shutter[i].acceleratorshutter_position[i] = ShutterRealToPercentPosition(Shutter[i].real_position, i); - Shutter[i].start_position = Shutter[i].real_position; + if (deltatime >= 0) { + Shutter[i].last_reported_time = Shutter[i].time+1; + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Time %d(%d), cStop %d, cVelo %d, mVelo %d, aVelo %d, mRun %d, aPos %d, aPos2 %d, nStop %d, Trgt %d, mVelo %d, Dir %d, Tilt %d, TrgtTilt: %d, Tiltmove: %d"), + Shutter[i].time, deltatime, current_stop_way, current_pwm_velocity, velocity_max, Shutter[i].accelerator, min_runtime_ms, current_real_position,Shutter[i].real_position, + next_possible_stop_position, Shutter[i].target_position, velocity_change_per_step_max, Shutter[i].direction,Shutter[i].tilt_real_pos, Shutter[i].tilt_target_pos, + Shutter[i].tiltmoving); + if ( ((Shutter[i].real_position * Shutter[i].direction >= Shutter[i].target_position * Shutter[i].direction && Shutter[i].tiltmoving==0) || + ((int16_t)Shutter[i].tilt_real_pos * Shutter[i].direction * Shutter[i].tilt_config[2] >= (int16_t)Shutter[i].tilt_target_pos * Shutter[i].direction * Shutter[i].tilt_config[2] && Shutter[i].tiltmoving==1)) + || (ShutterGlobal.position_mode == SHT_COUNTER && Shutter[i].accelerator <0 && Shutter[i].pwm_velocity+Shutter[i].acceleratorshutter_position[i] = ShutterRealToPercentPosition(Shutter[i].real_position, i); + Shutter[i].start_position = Shutter[i].real_position; - // manage venetian blinds - Shutter[i].tilt_target_pos = Settings->shutter_position[i] == 0 ? Shutter[i].tilt_config[0] : Shutter[i].tilt_target_pos; - Shutter[i].tilt_target_pos = Settings->shutter_position[i] == 100 ? Shutter[i].tilt_config[1] : Shutter[i].tilt_target_pos; - //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Pre: Tilt not match %d -> %d, moving: %d"),Shutter[i].tilt_real_pos,Shutter[i].tilt_target_pos,Shutter[i].tiltmoving); - if (abs(Shutter[i].tilt_real_pos - Shutter[i].tilt_target_pos) > Shutter[i].min_TiltChange && Shutter[i].tiltmoving == 0) { - AddLog(LOG_LEVEL_INFO, PSTR("SHT: Tilt not match %d -> %d"),Shutter[i].tilt_real_pos,Shutter[i].tilt_target_pos); - XdrvMailbox.payload = -99; - XdrvMailbox.index = i+1; - Shutter[i].tiltmoving = 1; - CmndShutterPosition(); - return; - } else { - Settings->shutter_tilt_pos[i] = Shutter[i].tilt_real_pos; - } - ShutterLogPos(i); + // manage venetian blinds + Shutter[i].tilt_target_pos = Settings->shutter_position[i] == 0 ? Shutter[i].tilt_config[0] : Shutter[i].tilt_target_pos; + Shutter[i].tilt_target_pos = Settings->shutter_position[i] == 100 ? Shutter[i].tilt_config[1] : Shutter[i].tilt_target_pos; + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Pre: Tilt not match %d -> %d, moving: %d"),Shutter[i].tilt_real_pos,Shutter[i].tilt_target_pos,Shutter[i].tiltmoving); + if (abs(Shutter[i].tilt_real_pos - Shutter[i].tilt_target_pos) > Shutter[i].min_TiltChange && Shutter[i].tiltmoving == 0) { + AddLog(LOG_LEVEL_INFO, PSTR("SHT: Tilt not match %d -> %d"),Shutter[i].tilt_real_pos,Shutter[i].tilt_target_pos); + XdrvMailbox.payload = -99; + XdrvMailbox.index = i+1; + Shutter[i].tiltmoving = 1; + CmndShutterPosition(); + return; + } else { + Settings->shutter_tilt_pos[i] = Shutter[i].tilt_real_pos; + } + ShutterLogPos(i); - // sending MQTT result to broker - snprintf_P(scommand, sizeof(scommand),PSTR(D_SHUTTER "%d"), i+1); - GetTopic_P(stopic, STAT, TasmotaGlobal.mqtt_topic, scommand); - Response_P("%d", (Settings->shutter_options[i] & 1) ? 100 - Settings->shutter_position[i]: Settings->shutter_position[i]); - MqttPublish(stopic, Settings->flag.mqtt_power_retain); // CMND_POWERRETAIN - ShutterReportPosition(true, i); - TasmotaGlobal.rules_flag.shutter_moved = 1; - XdrvRulesProcess(0); + // sending MQTT result to broker + snprintf_P(scommand, sizeof(scommand),PSTR(D_SHUTTER "%d"), i+1); + GetTopic_P(stopic, STAT, TasmotaGlobal.mqtt_topic, scommand); + Response_P("%d", (Settings->shutter_options[i] & 1) ? 100 - Settings->shutter_position[i]: Settings->shutter_position[i]); + MqttPublish(stopic, Settings->flag.mqtt_power_retain); // CMND_POWERRETAIN + ShutterReportPosition(true, i); + TasmotaGlobal.rules_flag.shutter_moved = 1; + XdrvRulesProcess(0); + } // timeloop } } } @@ -594,7 +598,7 @@ void ShutterAllowPreStartProcedure(uint8_t i) #ifdef USE_RULES uint32_t uptime_Local=0; AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Delay Start? var%d <99>=<%s>, max10s?"),i+1, rules_vars[i]); - TasmotaGlobal.rules_flag.shutter_moving = 1; + //TasmotaGlobal.rules_flag.shutter_moving = 1; XdrvRulesProcess(0); uptime_Local = TasmotaGlobal.uptime; while (uptime_Local+10 > TasmotaGlobal.uptime && (String)rules_vars[i] == "99") { @@ -1660,9 +1664,12 @@ bool Xdrv27(uint8_t function) case FUNC_PRE_INIT: ShutterInit(); break; - case FUNC_EVERY_50_MSECOND: + case FUNC_LOOP: ShutterUpdatePosition(); break; +// case FUNC_EVERY_50_MSECOND: +// ShutterUpdatePosition(); +// break; case FUNC_EVERY_SECOND: //case FUNC_EVERY_250_MSECOND: ShutterReportPosition(false, MAX_SHUTTERS); From d20ac1138ac9fe9f68a916155328d7d3e4290538 Mon Sep 17 00:00:00 2001 From: stefanbode Date: Tue, 16 Nov 2021 21:11:34 +0100 Subject: [PATCH 052/185] Update xdrv_27_shutter.ino --- tasmota/xdrv_27_shutter.ino | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 609dd7628..0f6cfb1b1 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -366,7 +366,6 @@ void ShutterInit(void) void ShutterReportPosition(bool always, uint32_t index) { Response_P(PSTR("{")); - //TasmotaGlobal.rules_flag.shutter_moving = 0; uint32_t i = 0; uint32_t n = TasmotaGlobal.shutters_present; if( index != MAX_SHUTTERS) { @@ -377,7 +376,6 @@ void ShutterReportPosition(bool always, uint32_t index) //AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d Real Pos %d"), i+1,Shutter[i].real_position); uint32_t position = ShutterRealToPercentPosition(Shutter[i].real_position, i); if (Shutter[i].direction != 0) { - //TasmotaGlobal.rules_flag.shutter_moving = 1; ShutterLogPos(i); } if (i && index == MAX_SHUTTERS) { ResponseAppend_P(PSTR(",")); } @@ -385,7 +383,7 @@ void ShutterReportPosition(bool always, uint32_t index) ResponseAppend_P(JSON_SHUTTER_POS, i+1, (Settings->shutter_options[i] & 1) ? 100-position : position, Shutter[i].direction,(Settings->shutter_options[i] & 1) ? 100-target : target, Shutter[i].tilt_real_pos ); } ResponseJsonEnd(); - if (always || (TasmotaGlobal.rules_flag.shutter_moving)) { + if (always || Shutter[i].direction != 0) { MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR(D_PRFX_SHUTTER)); // RulesProcess() now re-entry protected } //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: rules_flag.shutter_moving: %d, moved %d"), TasmotaGlobal.rules_flag.shutter_moving, TasmotaGlobal.rules_flag.shutter_moved); @@ -480,7 +478,7 @@ void ShutterPowerOff(uint8_t i) if (Shutter[i].direction !=0) { Shutter[i].direction = 0; } - TasmotaGlobal.rules_flag.shutter_moving = 0; + TasmotaGlobal.rules_flag.shutter_moved = 1; switch (Shutter[i].switch_mode) { case SHT_SWITCH: if ((1 << (Settings->shutter_startrelay[i]-1)) & TasmotaGlobal.power) { @@ -598,7 +596,6 @@ void ShutterAllowPreStartProcedure(uint8_t i) #ifdef USE_RULES uint32_t uptime_Local=0; AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Delay Start? var%d <99>=<%s>, max10s?"),i+1, rules_vars[i]); - //TasmotaGlobal.rules_flag.shutter_moving = 1; XdrvRulesProcess(0); uptime_Local = TasmotaGlobal.uptime; while (uptime_Local+10 > TasmotaGlobal.uptime && (String)rules_vars[i] == "99") { @@ -637,6 +634,7 @@ void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) // avoid file system writes during move to minimize missing steps savedata_original = Settings->save_data; Settings->save_data = 0; // will be restored after movement + TasmotaGlobal.save_data_counter = Settings->save_data; ShutterGlobal.skip_relay_change = 0; TasmotaGlobal.rules_flag.shutter_moved = 0; @@ -1664,12 +1662,9 @@ bool Xdrv27(uint8_t function) case FUNC_PRE_INIT: ShutterInit(); break; - case FUNC_LOOP: + case FUNC_EVERY_50_MSECOND: ShutterUpdatePosition(); break; -// case FUNC_EVERY_50_MSECOND: -// ShutterUpdatePosition(); -// break; case FUNC_EVERY_SECOND: //case FUNC_EVERY_250_MSECOND: ShutterReportPosition(false, MAX_SHUTTERS); From 8679cf52f5790209291d039388e78e2f35c0a90c Mon Sep 17 00:00:00 2001 From: stefanbode Date: Tue, 16 Nov 2021 21:21:04 +0100 Subject: [PATCH 053/185] Update xdrv_27_shutter.ino --- tasmota/xdrv_27_shutter.ino | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 0f6cfb1b1..a85ef0355 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -368,6 +368,7 @@ void ShutterReportPosition(bool always, uint32_t index) Response_P(PSTR("{")); uint32_t i = 0; uint32_t n = TasmotaGlobal.shutters_present; + uint8_t shutter_running = 0; if( index != MAX_SHUTTERS) { i = index; n = index+1; @@ -377,13 +378,14 @@ void ShutterReportPosition(bool always, uint32_t index) uint32_t position = ShutterRealToPercentPosition(Shutter[i].real_position, i); if (Shutter[i].direction != 0) { ShutterLogPos(i); + shutter_running++; } if (i && index == MAX_SHUTTERS) { ResponseAppend_P(PSTR(",")); } uint32_t target = ShutterRealToPercentPosition(Shutter[i].target_position, i); ResponseAppend_P(JSON_SHUTTER_POS, i+1, (Settings->shutter_options[i] & 1) ? 100-position : position, Shutter[i].direction,(Settings->shutter_options[i] & 1) ? 100-target : target, Shutter[i].tilt_real_pos ); } ResponseJsonEnd(); - if (always || Shutter[i].direction != 0) { + if (always || shutter_running) { MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR(D_PRFX_SHUTTER)); // RulesProcess() now re-entry protected } //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: rules_flag.shutter_moving: %d, moved %d"), TasmotaGlobal.rules_flag.shutter_moving, TasmotaGlobal.rules_flag.shutter_moved); From c4091c575bcb904577fb613b76af5594f8b04252 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Tue, 16 Nov 2021 21:46:42 +0100 Subject: [PATCH 054/185] Berry simplified preinit and autoexec --- lib/libesp32/Berry/default/berry_conf.h | 6 +++ .../Berry/default/embedded/autoconf.be | 2 + lib/libesp32/Berry/src/be_vm.c | 4 +- tasmota/xdrv_52_9_berry.ino | 37 ++----------------- 4 files changed, 13 insertions(+), 36 deletions(-) diff --git a/lib/libesp32/Berry/default/berry_conf.h b/lib/libesp32/Berry/default/berry_conf.h index 3360b9082..e11d6c3cb 100644 --- a/lib/libesp32/Berry/default/berry_conf.h +++ b/lib/libesp32/Berry/default/berry_conf.h @@ -100,6 +100,12 @@ **/ #define BE_STACK_FREE_MIN 20 +/* Macro: BE_STACK_START + * Set the starting size of the stack at VM creation. + * Default: 50 + **/ +#define BE_STACK_START 100 + /* Macro: BE_CONST_SEARCH_SIZE * Constants in function are limited to 255. However the compiler * will look for a maximum of pre-existing constants to avoid diff --git a/lib/libesp32/Berry/default/embedded/autoconf.be b/lib/libesp32/Berry/default/embedded/autoconf.be index 3f9586e04..a30ed2044 100644 --- a/lib/libesp32/Berry/default/embedded/autoconf.be +++ b/lib/libesp32/Berry/default/embedded/autoconf.be @@ -293,6 +293,7 @@ autoconf_module.init = def (m) self._error = nil end + # called by the synthetic event `preinit` def preinit() if self._archive == nil return end # try to launch `preinit.be` @@ -327,6 +328,7 @@ autoconf_module.init = def (m) end end + # called by the synthetic event `autoexec` def autoexec() if self._archive == nil return end # try to launch `preinit.be` diff --git a/lib/libesp32/Berry/src/be_vm.c b/lib/libesp32/Berry/src/be_vm.c index ac2ede585..48834910e 100644 --- a/lib/libesp32/Berry/src/be_vm.c +++ b/lib/libesp32/Berry/src/be_vm.c @@ -453,8 +453,8 @@ BERRY_API bvm* be_vm_new(void) be_stack_init(vm, &vm->refstack, sizeof(binstance*)); be_stack_init(vm, &vm->exceptstack, sizeof(struct bexecptframe)); be_stack_init(vm, &vm->tracestack, sizeof(bcallsnapshot)); - vm->stack = be_malloc(vm, sizeof(bvalue) * BE_STACK_FREE_MIN); - vm->stacktop = vm->stack + BE_STACK_FREE_MIN; + vm->stack = be_malloc(vm, sizeof(bvalue) * BE_STACK_START); + vm->stacktop = vm->stack + BE_STACK_START; vm->reg = vm->stack; vm->top = vm->reg; be_globalvar_init(vm); diff --git a/tasmota/xdrv_52_9_berry.ino b/tasmota/xdrv_52_9_berry.ino index 46cc5692f..84a7b962a 100644 --- a/tasmota/xdrv_52_9_berry.ino +++ b/tasmota/xdrv_52_9_berry.ino @@ -241,34 +241,6 @@ int32_t callBerryEventDispatcher(const char *type, const char *cmd, int32_t idx, return ret; } -// call a method in autoconf -int32_t callBerryAutoconf(const char * method) { - int32_t ret = 0; - bvm *vm = berry.vm; - - if (nullptr == vm) { return ret; } - checkBeTop(); - be_getglobal(vm, "autoconf"); - if (!be_isnil(vm, -1)) { - be_getmethod(vm, -1, method); - if (!be_isnil(vm, -1)) { - be_pushvalue(vm, -2); - BrTimeoutStart(); - ret = be_pcall(vm, 1); // 1 arg - BrTimeoutReset(); - if (ret != 0) { - BerryDumpErrorAndClear(vm, false); // log in Tasmota console only - return ret; - } - be_pop(vm, 1); // remove instance - } - be_pop(vm, 1); // remove method - } - be_pop(vm, 1); // remove instance object - checkBeTop(); - return ret; -} - /*********************************************************************************************\ * VM Observability \*********************************************************************************************/ @@ -364,9 +336,9 @@ void BerryInit(void) { AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_BERRY "Berry initialized, RAM used=%u"), callBerryGC()); berry_init_ok = true; - // Run 'autoconf.preinit()' - callBerryAutoconf("preinit"); - + // we generate a synthetic event `autoexec` + callBerryEventDispatcher(PSTR("preinit"), nullptr, 0, nullptr); + // Run pre-init BrLoad("preinit.be"); // run 'preinit.be' if present } while (0); @@ -790,9 +762,6 @@ bool Xdrv52(uint8_t function) // break; case FUNC_LOOP: if (!berry.autoexec_done) { - // Run 'autoconf.preinit()' - callBerryAutoconf("autoexec"); - // we generate a synthetic event `autoexec` callBerryEventDispatcher(PSTR("autoexec"), nullptr, 0, nullptr); From aca4223ad6b285b8734a1238726fd972af8e602c Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Tue, 16 Nov 2021 22:21:44 +0100 Subject: [PATCH 055/185] ESP32 fix leftover GPIO configuration after restart --- CHANGELOG.md | 1 + tasmota/support_tasmota.ino | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf3b47477..3c68385d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file. ## [10.0.0.3] ### Added - Autoconfiguration for ESP32 and variants +- ESP32 fix leftover GPIO configuration after restart ### Changed - ESP8266 Gratuitous ARP enabled and set to 60 seconds (#13623) diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 10bbcc495..bfe894446 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -1651,6 +1651,22 @@ void ResetPwm(void) /********************************************************************************************/ +#ifdef ESP32 +// Since ESP-IDF 4.4, GPIO matrix or I/O is not reset during a restart +// and GPIO configuration can get stuck because of leftovers +// +// This patched version of pinMode forces a full GPIO reset before setting new mode +// +extern "C" void ARDUINO_ISR_ATTR __pinMode(uint8_t pin, uint8_t mode); + +extern "C" void ARDUINO_ISR_ATTR pinMode(uint8_t pin, uint8_t mode) { + gpio_reset_pin((gpio_num_t)pin); + __pinMode(pin, mode); +} +#endif + +/********************************************************************************************/ + void GpioInit(void) { if (!ValidModule(Settings->module)) { From 7f8ca14770d7466efcbbe5c75ac07abbb3e84f5c Mon Sep 17 00:00:00 2001 From: Adrian Scillato Date: Tue, 16 Nov 2021 19:10:25 -0300 Subject: [PATCH 056/185] Fix NTC Temp support for ESP32 --- tasmota/xsns_02_analog.ino | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tasmota/xsns_02_analog.ino b/tasmota/xsns_02_analog.ino index 1e69da349..c6fce4051 100644 --- a/tasmota/xsns_02_analog.ino +++ b/tasmota/xsns_02_analog.ino @@ -43,7 +43,7 @@ // Parameters for equation #define ANALOG_V33 3.3 // ESP8266 / ESP32 Analog voltage -#define ANALOG_T0 TO_KELVIN(25.0) // 25 degrees Celcius in Kelvin (= 298.15) +#define ANALOG_T0 TO_KELVIN(25.0) // 25 degrees Celsius in Kelvin (= 298.15) // Shelly 2.5 NTC Thermistor // 3V3 --- ANALOG_NTC_BRIDGE_RESISTANCE ---v--- NTC --- Gnd @@ -409,8 +409,15 @@ void AdcEverySecond(void) { for (uint32_t idx = 0; idx < Adcs.present; idx++) { if (ADC_TEMP == Adc[idx].type) { int adc = AdcRead(Adc[idx].pin, 2); - // Steinhart-Hart equation for thermistor as temperature sensor + // Steinhart-Hart equation for thermistor as temperature sensor: + // double Rt = (adc * Adc[idx].param1 * MAX_ADC_V) / (ANALOG_RANGE * ANALOG_V33 - (double)adc * MAX_ADC_V); + // MAX_ADC_V in ESP8266 is 1 + // MAX_ADC_V in ESP32 is 3.3 +#ifdef ESP8266 double Rt = (adc * Adc[idx].param1) / (ANALOG_RANGE * ANALOG_V33 - (double)adc); // Shelly param1 = 32000 (ANALOG_NTC_BRIDGE_RESISTANCE) +#else + double Rt = (adc * Adc[idx].param1) / (ANALOG_RANGE - (double)adc); +#endif double BC = (double)Adc[idx].param3 / 10000; // Shelly param3 = 3350 (ANALOG_NTC_B_COEFFICIENT) double T = BC / (BC / ANALOG_T0 + TaylorLog(Rt / (double)Adc[idx].param2)); // Shelly param2 = 10000 (ANALOG_NTC_RESISTANCE) Adc[idx].temperature = ConvertTemp(TO_CELSIUS(T)); From 152663e021e6217fdd885f29d44e1a41086c7c18 Mon Sep 17 00:00:00 2001 From: stefanbode Date: Wed, 17 Nov 2021 11:28:27 +0100 Subject: [PATCH 057/185] Update xdrv_27_shutter.ino --- tasmota/xdrv_27_shutter.ino | 79 ++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 41 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index a85ef0355..f7ddfb222 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -125,7 +125,6 @@ void ShutterLogPos(uint32_t i) AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d Real %d, Start %d, Stop %d, Dir %d, Delay %d, Rtc %s [s], Freq %d, PWM %d, Tilt %d"), i+1, Shutter[i].real_position, Shutter[i].start_position, Shutter[i].target_position, Shutter[i].direction, Shutter[i].motordelay, stemp2, Shutter[i].pwm_velocity, Shutter[i].pwm_value,Shutter[i].tilt_real_pos); - yield(); } void ExecuteCommandPowerShutter(uint32_t device, uint32_t state, uint32_t source) @@ -537,48 +536,46 @@ void ShutterUpdatePosition(void) ShutterGlobal.start_reported = 1; } int32_t deltatime = Shutter[i].time-Shutter[i].last_reported_time; - if (deltatime >= 0) { - Shutter[i].last_reported_time = Shutter[i].time+1; - AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Time %d(%d), cStop %d, cVelo %d, mVelo %d, aVelo %d, mRun %d, aPos %d, aPos2 %d, nStop %d, Trgt %d, mVelo %d, Dir %d, Tilt %d, TrgtTilt: %d, Tiltmove: %d"), - Shutter[i].time, deltatime, current_stop_way, current_pwm_velocity, velocity_max, Shutter[i].accelerator, min_runtime_ms, current_real_position,Shutter[i].real_position, - next_possible_stop_position, Shutter[i].target_position, velocity_change_per_step_max, Shutter[i].direction,Shutter[i].tilt_real_pos, Shutter[i].tilt_target_pos, - Shutter[i].tiltmoving); - if ( ((Shutter[i].real_position * Shutter[i].direction >= Shutter[i].target_position * Shutter[i].direction && Shutter[i].tiltmoving==0) || - ((int16_t)Shutter[i].tilt_real_pos * Shutter[i].direction * Shutter[i].tilt_config[2] >= (int16_t)Shutter[i].tilt_target_pos * Shutter[i].direction * Shutter[i].tilt_config[2] && Shutter[i].tiltmoving==1)) - || (ShutterGlobal.position_mode == SHT_COUNTER && Shutter[i].accelerator <0 && Shutter[i].pwm_velocity+Shutter[i].acceleratorshutter_position[i] = ShutterRealToPercentPosition(Shutter[i].real_position, i); - Shutter[i].start_position = Shutter[i].real_position; + Shutter[i].last_reported_time = Shutter[i].time+1; + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Time %d(%d), cStop %d, cVelo %d, mVelo %d, aVelo %d, mRun %d, aPos %d, aPos2 %d, nStop %d, Trgt %d, mVelo %d, Dir %d, Tilt %d, TrgtTilt: %d, Tiltmove: %d"), + Shutter[i].time, deltatime, current_stop_way, current_pwm_velocity, velocity_max, Shutter[i].accelerator, min_runtime_ms, current_real_position,Shutter[i].real_position, + next_possible_stop_position, Shutter[i].target_position, velocity_change_per_step_max, Shutter[i].direction,Shutter[i].tilt_real_pos, Shutter[i].tilt_target_pos, + Shutter[i].tiltmoving); + if ( ((Shutter[i].real_position * Shutter[i].direction >= Shutter[i].target_position * Shutter[i].direction && Shutter[i].tiltmoving==0) || + ((int16_t)Shutter[i].tilt_real_pos * Shutter[i].direction * Shutter[i].tilt_config[2] >= (int16_t)Shutter[i].tilt_target_pos * Shutter[i].direction * Shutter[i].tilt_config[2] && Shutter[i].tiltmoving==1)) + || (ShutterGlobal.position_mode == SHT_COUNTER && Shutter[i].accelerator <0 && Shutter[i].pwm_velocity+Shutter[i].acceleratorshutter_position[i] = ShutterRealToPercentPosition(Shutter[i].real_position, i); + Shutter[i].start_position = Shutter[i].real_position; - // manage venetian blinds - Shutter[i].tilt_target_pos = Settings->shutter_position[i] == 0 ? Shutter[i].tilt_config[0] : Shutter[i].tilt_target_pos; - Shutter[i].tilt_target_pos = Settings->shutter_position[i] == 100 ? Shutter[i].tilt_config[1] : Shutter[i].tilt_target_pos; - //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Pre: Tilt not match %d -> %d, moving: %d"),Shutter[i].tilt_real_pos,Shutter[i].tilt_target_pos,Shutter[i].tiltmoving); - if (abs(Shutter[i].tilt_real_pos - Shutter[i].tilt_target_pos) > Shutter[i].min_TiltChange && Shutter[i].tiltmoving == 0) { - AddLog(LOG_LEVEL_INFO, PSTR("SHT: Tilt not match %d -> %d"),Shutter[i].tilt_real_pos,Shutter[i].tilt_target_pos); - XdrvMailbox.payload = -99; - XdrvMailbox.index = i+1; - Shutter[i].tiltmoving = 1; - CmndShutterPosition(); - return; - } else { - Settings->shutter_tilt_pos[i] = Shutter[i].tilt_real_pos; - } - ShutterLogPos(i); + // manage venetian blinds + Shutter[i].tilt_target_pos = Settings->shutter_position[i] == 0 ? Shutter[i].tilt_config[0] : Shutter[i].tilt_target_pos; + Shutter[i].tilt_target_pos = Settings->shutter_position[i] == 100 ? Shutter[i].tilt_config[1] : Shutter[i].tilt_target_pos; + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Pre: Tilt not match %d -> %d, moving: %d"),Shutter[i].tilt_real_pos,Shutter[i].tilt_target_pos,Shutter[i].tiltmoving); + if (abs(Shutter[i].tilt_real_pos - Shutter[i].tilt_target_pos) > Shutter[i].min_TiltChange && Shutter[i].tiltmoving == 0) { + AddLog(LOG_LEVEL_INFO, PSTR("SHT: Tilt not match %d -> %d"),Shutter[i].tilt_real_pos,Shutter[i].tilt_target_pos); + XdrvMailbox.payload = -99; + XdrvMailbox.index = i+1; + Shutter[i].tiltmoving = 1; + CmndShutterPosition(); + return; + } else { + Settings->shutter_tilt_pos[i] = Shutter[i].tilt_real_pos; + } + ShutterLogPos(i); - // sending MQTT result to broker - snprintf_P(scommand, sizeof(scommand),PSTR(D_SHUTTER "%d"), i+1); - GetTopic_P(stopic, STAT, TasmotaGlobal.mqtt_topic, scommand); - Response_P("%d", (Settings->shutter_options[i] & 1) ? 100 - Settings->shutter_position[i]: Settings->shutter_position[i]); - MqttPublish(stopic, Settings->flag.mqtt_power_retain); // CMND_POWERRETAIN - ShutterReportPosition(true, i); - TasmotaGlobal.rules_flag.shutter_moved = 1; - XdrvRulesProcess(0); - } // timeloop + // sending MQTT result to broker + snprintf_P(scommand, sizeof(scommand),PSTR(D_SHUTTER "%d"), i+1); + GetTopic_P(stopic, STAT, TasmotaGlobal.mqtt_topic, scommand); + Response_P("%d", (Settings->shutter_options[i] & 1) ? 100 - Settings->shutter_position[i]: Settings->shutter_position[i]); + MqttPublish(stopic, Settings->flag.mqtt_power_retain); // CMND_POWERRETAIN + ShutterReportPosition(true, i); + TasmotaGlobal.rules_flag.shutter_moved = 1; + XdrvRulesProcess(0); } } } From b19d1c580f6f7d055d7578fdde32d81514ab3e1a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 17 Nov 2021 17:25:16 +0100 Subject: [PATCH 058/185] Add Sonoff SPM POC Add Sonoff SPM POC (#13447) --- CHANGELOG.md | 1 + RELEASENOTES.md | 1 + tasmota/xdrv_86_esp32_sonoff_spm.ino | 1129 ++++++++++++++++++++++++++ 3 files changed, 1131 insertions(+) create mode 100644 tasmota/xdrv_86_esp32_sonoff_spm.ino diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c68385d0..0d3711803 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. ### Added - Autoconfiguration for ESP32 and variants - ESP32 fix leftover GPIO configuration after restart +- ESP32 Proof of Concept Sonoff SPM with limited functionality (switching and energy monitoring) (#13447) ### Changed - ESP8266 Gratuitous ARP enabled and set to 60 seconds (#13623) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 858ab7ac7..c73e1da40 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -104,6 +104,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo ### Added - 1 second heartbeat GPIO - ESP32 Berry add module ``python_compat`` to be closer to Python syntax [#13428](https://github.com/arendst/Tasmota/issues/13428) +- ESP32 Proof of Concept Sonoff SPM with limited functionality (switching and energy monitoring) [#13447](https://github.com/arendst/Tasmota/issues/13447) - Command ``TcpConfig`` for TCPBridge protocol configuration [#13565](https://github.com/arendst/Tasmota/issues/13565) - Support for HDC2010 temperature/humidity sensor by Luc Boudreau [#13633](https://github.com/arendst/Tasmota/issues/13633) diff --git a/tasmota/xdrv_86_esp32_sonoff_spm.ino b/tasmota/xdrv_86_esp32_sonoff_spm.ino new file mode 100644 index 000000000..f40c824fa --- /dev/null +++ b/tasmota/xdrv_86_esp32_sonoff_spm.ino @@ -0,0 +1,1129 @@ +/* + xdrv_86_esp32_sonoff_spm.ino - Sonoff SPM support for Tasmota + + Copyright (C) 2021 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +//#define USE_SONOFF_SPM + +#ifdef ESP32 +#ifdef USE_SONOFF_SPM +/*********************************************************************************************\ + * Sonoff Stackable Power Manager (Current state: PROOF OF CONCEPT) + * + * {"NAME":"Sonoff SPM (POC1)","GPIO":[1,1,1,1,3200,1,1,1,1,1,1,1,3232,1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,544,1,1,32,1,0,0,1],"FLAG":0,"BASE":1} + * + * Things to know: + * Bulk of the action is handled by ARM processors present in every unit communicating over modbus RS-485. + * Each SPM-4Relay has 4 bistable relays with their own CSE7761 energy monitoring device handled by an ARM processor. + * Green led is controlled by ARM processor indicating SD-Card access. + * ESP32 is used as interface between Welink and ARM processor in SPM-Main unit communicating over proprietary serial protocol. + * Inductive/Capacitive loads are not reported correctly. + * Power on sequence for two SPM-4Relay modules is 00-00-15-10-(0F)-(13)-(13)-(19)-0C-09-04-09-04-0B-0B + * + * Tasmota POC1: + * Up to 7 SPM-4Relay units supporting up to 28 relays. + * Gui rotating energy display for 4 relays at a time. + * Button on SPM-Main initiates re-scan of SPM-4Relay units. + * Blue led equals Tasmota WiFi status. + * + * Todo: + * Ethernet support (Find correct MDIO, MDC, POWER GPIO's and ETH_ parameters). + * Gui optimization for energy display. + * Gui for Overload Protection entry (is handled by ARM processor). + * Gui for Scheduling entry (is handled by ARM processor). + * Yellow led functionality. + * Interpretation of reset sequence on GPIO's 12-14. + * + * Nice to have: + * Support for all 32 SPM4Relay units equals 128 relays + * + * GPIO's used: + * GPIO00 - Bootmode / serial flash + * GPIO01 - Serial console TX (921600bps8N1 originally) + * GPIO03 - Serial console RX + * GPIO04 - ARM processor TX (115200bps8N1) + * GPIO12 - SPI MISO ARM pulsetrain code (input?) + * GPIO13 - SPI CLK + * GPIO14 - SPI CS ARM pulsetrain eoc (input?) + * GPIO15 - ARM reset (output) - 18ms low active 125ms after restart esp32 + * GPIO16 - ARM processor RX + * GPIO17 - EMAC_CLK_OUT_180 + * GPIO18 - ??ETH MDIO + * GPIO19 - EMAC_TXD0(RMII) + * GPIO21 - EMAC_TX_EN(RMII) + * GPIO22 - EMAC_TXD1(RMII) + * GPIO23 - ??ETH MDC + * GPIO25 - EMAC_RXD0(RMII) + * GPIO26 - EMAC_RXD1(RMII) + * GPIO27 - EMAC_RX_CRS_DV + * GPIO?? - ??ETH POWER + * GPIO32 - Blue status led2 + * GPIO33 - Yellow error led3 + * GPIO35 - Button + * #define ETH_TYPE ETH_PHY_LAN8720 + * #define ETH_CLKMODE ETH_CLOCK_GPIO0_IN + * #define ETH_ADDRESS 0 + * + * Variables used: + * module = 0 to 31 SPM-4Relays + * channel = 0 to 3 or 01, 02, 04, 08 Bitmask of four relays in module + * relay = 0 to 127 Relays +\*********************************************************************************************/ + +#define XDRV_86 86 + +#define SSPM_MAX_MODULES 7 // Currently supports up to 7 SPM-4RELAY units for a total of 28 relays restricted by power_t size +#define SSPM_SERIAL_BUFFER_SIZE 512 // Needs to accomodate Energy total history for six months (408 bytes) + +// Send +#define SSPM_FUNC_FIND 0 // 0x00 +#define SSPM_FUNC_SET_OPS 3 // 0x03 - Overload Protection +#define SSPM_FUNC_GET_OPS 4 // 0x04 +#define SSPM_FUNC_SET_RELAY 8 // 0x08 +#define SSPM_FUNC_GET_MODULE_STATE 9 // 0x09 - State of four channels +#define SSPM_FUNC_SET_SCHEME 10 // 0x0A +#define SSPM_FUNC_GET_SCHEME 11 // 0x0B +#define SSPM_FUNC_SET_TIME 12 // 0x0C +#define SSPM_FUNC_INIT_SCAN 16 // 0x10 +#define SSPM_FUNC_UNITS 21 // 0x15 +#define SSPM_FUNC_GET_ENERGY_TOTAL 22 // 0x16 +#define SSPM_FUNC_GET_ENERGY 24 // 0x18 +#define SSPM_FUNC_GET_LOG 26 // 0x1A + +#define SSPM_FUNC_ENERGY_PERIOD 27 // 0x1B + +// Receive +#define SSPM_FUNC_ENERGY_RESULT 6 // 0x06 +#define SSPM_FUNC_KEY_PRESS 7 // 0x07 +#define SSPM_FUNC_SCAN_START 15 // 0x0F +#define SSPM_FUNC_SCAN_RESULT 19 // 0x13 +#define SSPM_FUNC_SCAN_DONE 25 // 0x19 + +#define SSPM_GPIO_ARM_TX 4 +#define SSPM_GPIO_ARM_RX 16 +#define SSPM_GPIO_ARM_RESET 15 +#define SSPM_GPIO_PULSE_OUT 13 +#define SSPM_GPIO_PULSE_IN1 12 +#define SSPM_GPIO_PULSE_IN2 14 +#define SSPM_GPIO_LED_STATUS 32 +#define SSPM_GPIO_LED_ERROR 33 + +#define SSPM_MODULE_NAME_SIZE 12 + +enum SspmInitSteps { SPM_NONE, SPM_WAIT, SPM_RESET, SPM_POLL, SPM_POLL_ACK, SPM_SEND_FUNC_UNITS, SPM_STEP_WAIT2, + SPM_DEVICES_FOUND, + SPM_GET_ENERGY_TOTALS, + SPM_ALLOW_LOOP}; + +#include +TasmotaSerial *SspmSerial; + +typedef struct { + float voltage[SSPM_MAX_MODULES][4]; // 123.12 V + float current[SSPM_MAX_MODULES][4]; // 123.12 A + float active_power[SSPM_MAX_MODULES][4]; // 123.12 W + float apparent_power[SSPM_MAX_MODULES][4]; // 123.12 VA + float reactive_power[SSPM_MAX_MODULES][4]; // 123.12 VAr + float power_factor[SSPM_MAX_MODULES][4]; // 0.12 + float total[SSPM_MAX_MODULES][4]; // 12345 kWh total energy + + uint32_t timeout; + power_t old_power; + uint16_t serial_in_byte_counter; + uint16_t expected_bytes; + uint8_t module[SSPM_MAX_MODULES][SSPM_MODULE_NAME_SIZE]; + + uint8_t allow_updates; + uint8_t get_energy_relay; + uint8_t rotate; + uint8_t module_max; + uint8_t module_selected; + uint8_t no_send_key; + uint8_t counter; + uint8_t command_sequence; + uint8_t loop_step; + uint8_t init_step; + uint8_t last_button; + bool discovery_triggered; +} TSspm; + +uint8_t *SspmBuffer = nullptr; +TSspm *Sspm = nullptr; + +void SSPMSetLock(uint32_t seconds) { + Sspm->timeout = seconds * 10; // Decremented every 100mSec + Sspm->allow_updates = 0; // Disable requests from 100mSec loop +} + +uint16_t SSPMCalculateCRC(uint8_t *frame, uint32_t num) { + // CRC-16/ARC (polynomial 0x8005 reflected as 0xA001) + uint16_t crc = 0; + for (uint32_t i = 2; i < num; i++) { + crc ^= frame[i]; + for (uint32_t i = 0; i < 8; i++) { + crc = (crc & 1) ? (crc >> 1) ^ 0xA001 : crc >> 1; + } + } + return crc ^ 0; +} + +void SSPMTime(uint8_t *frame) { + /* + 0 1 2 3 4 5 6 + YY YY MM DD HH MM SS + 07 e5 0b 06 0c 39 01 + */ + TIME_T time; + BreakTime(Rtc.utc_time, time); + uint16_t year = time.year + 1970; + frame[0] = year >> 8; + frame[1] = year; + frame[2] = time.month; + frame[3] = time.day_of_month; + frame[4] = time.hour; + frame[5] = time.minute; + frame[6] = time.second; +} + +void SSPMSend(uint32_t size) { + uint16_t crc = SSPMCalculateCRC(SspmBuffer, size -2); + SspmBuffer[size -2] = (uint8_t)(crc >> 8); + SspmBuffer[size -1] = (uint8_t)crc; + + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SPM: ESP %*_H"), size, SspmBuffer); + + SspmSerial->write(SspmBuffer, size); +} + +void SSPMInitSend(void) { + /* + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + Marker |Module id |Ac|Cm|Size | + */ + memset(SspmBuffer, 0, 19); + SspmBuffer[0] = 0xAA; + SspmBuffer[1] = 0x55; + SspmBuffer[2] = 0x01; +} + +void SSPMSendCmnd(uint32_t command) { + /* + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FC 51 + Marker |Module id |Ac|Cm|Size |Ix|Chksm| + */ + SSPMInitSend(); + SspmBuffer[16] = command; + if (0 == command) { + Sspm->command_sequence = 0; + } else { + Sspm->command_sequence++; + } + SspmBuffer[19] = Sspm->command_sequence; + + SSPMSend(22); +} + +void SSPMSendInitScan(void) { + /* + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 + AA 55 01 ff ff ff ff ff ff ff ff ff ff ff ff 00 10 00 00 02 cd f0 + Marker |Module id |Ac|Cm|Size |Ix|Chksm| + + Acknowledge: + AA 55 01 ff ff ff ff ff ff ff ff ff ff ff ff 80 10 00 01 00 02 e5 03 + |Ac|Cm|Size |Rt|Ix|Chksm| + */ + SSPMSetLock(30); // Disable requests from 100mSec loop + + memset(SspmBuffer, 0xFF, 15); + SspmBuffer[0] = 0xAA; + SspmBuffer[1] = 0x55; + SspmBuffer[2] = 0x01; + + SspmBuffer[15] = 0; + SspmBuffer[16] = SSPM_FUNC_INIT_SCAN; // 0x10 + SspmBuffer[17] = 0; + SspmBuffer[18] = 0; + Sspm->command_sequence++; + SspmBuffer[19] = Sspm->command_sequence; + + SSPMSend(22); + + AddLog(LOG_LEVEL_DEBUG, PSTR("SPM: Start relay scan...")); +} + +void SSPMSendOPS(uint32_t relay_num) { + /* + Overload Protection + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 + AA 55 01 6b 7e 32 37 39 37 34 13 4b 35 36 37 00 03 00 12 04 00 11 30 00 00 00 0a 00 f0 00 00 00 0a 00 14 00 00 fb a6 f8 = Default settings + Marker |Module id |Ac|Cm|Size |Ch|Ra|Max P |Min P |Max U |Min U |Max I |De|Ix|Chksm| + | | | 4400W| 0.1W| 240V| 0.1V| 20A| | + Ch - Bitmask channel 01 = 1, 02 = 2, 04 = 3, 08 = 4 + Ra - Bitmask enabled features xxxxxxx1 Enable Max current + Ra - Bitmask enabled features xxxxxx1x Enable Min voltage + Ra - Bitmask enabled features xxxxx1xx Enable Max voltage + Ra - Bitmask enabled features xxxx1xxx Enable Min power + Ra - Bitmask enabled features xxx1xxxx Enable Max power + De - 0 to 255 seconds Overload detection delay + Values are XX XX - number + XX - decimals + + Acknowledge: + AA 55 01 6b 7e 32 37 39 37 34 13 4b 35 36 37 80 03 00 01 00 14 08 bc + |Ac|Cm|Size |Rt|Ix|Chksm| + Ac - Acknowledge or error number + Rt - Return code + */ + + SspmBuffer[16] = SSPM_FUNC_SET_OPS; // 0x03 + +} + +void SSPMSendScheme(uint32_t relay) { + /* + Time scheme + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 + One time + AA 55 01 8b 34 32 37 39 37 34 13 4b 35 36 37 00 0a 00 1e 01 01 01 07 e5 0b 0e 0b 38 08 00 6b 01 00 ea 60 20 23 1b 04 fd 7a 83 05 63 ee dd a9 b9 3a 7e 14 95 + AA 55 01 8b 34 32 37 39 37 34 13 4b 35 36 37 00 0a 00 1e 01 01 01 07 e5 0b 0e 0c 04 35 00 55 01 02 46 76 0e 0c 20 e1 22 7c 67 ab 9c 66 73 6d bd e8 7f 50 d4 + Marker |Module id |Ac|Cm|Size |No| |Mo| YYYY|MM|DD|HH|MM |St|Re|Scheme id | + No - Number of schemes defined + Mo - Scheme type (1 = temporarly, 2 = scheduled) + Re - Relay 0 to 3 + St - State (0 = off, 1 = On) + + Scheduled On + AA 55 01 8b 34 32 37 39 37 34 13 4b 35 36 37 00 0a 00 18 01 01 02 15 0c 0c 01 03 99 65 93 dc f8 d0 b0 29 a8 66 ba 8f 41 66 29 24 80 5b 48 + AA 55 01 8b 34 32 37 39 37 34 13 4b 35 36 37 00 0a 00 18 01 01 02 15 0c 0c 01 03 99 65 93 dc f8 d0 b0 29 a8 66 ba 8f 41 66 29 24 82 9a c9 + AA 55 01 8b 34 32 37 39 37 34 13 4b 35 36 37 00 0a 00 18 01 01 02 53 0c 0c 01 03 99 65 93 dc f8 d0 b0 29 a8 66 ba 8f 41 66 29 24 83 44 aa + AA 55 01 8b 34 32 37 39 37 34 13 4b 35 36 37 00 0a 00 18 01 01 02 53 0d 0b 00 02 99 65 93 dc f8 d0 b0 29 a8 66 ba 8f 41 66 29 24 84 e0 22 + AA 55 01 8b 34 32 37 39 37 34 13 4b 35 36 37 00 0a 00 18 01 01 02 0e 0d 3b 01 03 84 fb ea 35 ca 16 51 b5 b8 10 a1 1c d0 1a 3f 7a 86 e3 fa + + AA 55 01 8b 34 32 37 39 37 34 13 4b 35 36 37 00 0a 00 2f 02 01 02 0e 0d 3b 01 03 84 fb ea 35 ca 16 51 b5 b8 10 a1 1c d0 1a 3f 7a + 01 02 53 0d 0b 00 02 99 65 93 dc f8 d0 b0 29 a8 66 ba 8f 41 66 29 24 87 e8 02 + + AA 55 01 8b 34 32 37 39 37 34 13 4b 35 36 37 00 0a 00 2f 02 01 02 53 0d 0b 00 02 99 65 93 dc f8 d0 b0 29 a8 66 ba 8f 41 66 29 24 + 01 02 0e 0d 3b 01 03 84 fb ea 35 ca 16 51 b5 b8 10 a1 1c d0 1a 3f 7a 89 6e e6 + + AA 55 01 8b 34 32 37 39 37 34 13 4b 35 36 37 00 0a 00 4c 03 01 01 07 e5 0b 0e 0e 0e 26 00 e7 01 00 e6 b2 48 8e ef be ce 78 3e 5d a8 3a c0 c5 6f 5e = One time + 01 02 53 0d 0b 00 02 99 65 93 dc f8 d0 b0 29 a8 66 ba 8f 41 66 29 24 = 14:11 OFF CH3 SuMoThSa + 01 02 0e 0d 3b 01 03 84 fb ea 35 ca 16 51 b5 b8 10 a1 1c d0 1a 3f 7a 8a 2f f8 = 14:59 ON CH4 MoTuWe + + Marker |Module id |Ac|Cm|Size |No| |Mo|Dy|HH|MM|St|Re|Scheme id | + Dy - Bitmask days xxxxxxx1 sunday + xxxxxx1x monday + xxxxx1xx tuesday + xxxx1xxx wednesday + xxx1xxxx thursday + xx1xxxxx friday + x1xxxxxx saturday + + Scheduled Off + AA 55 01 8b 34 32 37 39 37 34 13 4b 35 36 37 00 0a 00 01 00 81 26 9f + Schedule 2 off + AA 55 01 8b 34 32 37 39 37 34 13 4b 35 36 37 00 0a 00 18 01 01 02 53 0d 0b 00 02 99 65 93 dc f8 d0 b0 29 a8 66 ba 8f 41 66 29 24 88 e5 22 + Marker |Module id |Ac|Cm|Size | + */ + + SspmBuffer[16] = SSPM_FUNC_SET_SCHEME; // 0x0A + +} + +void SSPMSendSetTime(void) { + /* + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 0c 00 0b 07 e5 0b 06 0c 39 01 00 00 02 00 04 8a 37 + Marker |Module id |Ac|Cm|Size |YY YY MM DD HH MM SS|Ln|St|Tr| |Ix|Chksm| + */ + SSPMInitSend(); + SspmBuffer[16] = SSPM_FUNC_SET_TIME; + SspmBuffer[18] = 0x0B; + SSPMTime(SspmBuffer + 19); + SspmBuffer[26] = 0x00; + SspmBuffer[27] = 0x00; + SspmBuffer[28] = 0x02; + SspmBuffer[29] = 0x00; + Sspm->command_sequence++; + SspmBuffer[30] = Sspm->command_sequence; + + SSPMSend(33); +} + +void SSPMSendSetRelay(uint32_t relay, uint32_t state) { + /* + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 + AA 55 01 6b 7e 32 37 39 37 34 13 4b 35 36 37 00 08 00 01 44 08 c0 34 + Marker |Module id |Ac|Cm|Size |Pl|Ix|Chksm| + */ + uint8_t channel = 1 << (relay & 0x03); // Channel relays are bit masked + if (state) { + channel |= (channel << 4); + } + uint8_t module = relay >> 2; + SSPMInitSend(); + memcpy(SspmBuffer +3, Sspm->module[module], SSPM_MODULE_NAME_SIZE); + SspmBuffer[16] = SSPM_FUNC_SET_RELAY; + SspmBuffer[18] = 0x01; + SspmBuffer[19] = channel; + Sspm->command_sequence++; + SspmBuffer[20] = Sspm->command_sequence; + + SSPMSend(23); +} + +void SSPMSendGetModuleState(uint32_t module) { + /* + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 + AA 55 01 8b 34 32 37 39 37 34 13 4b 35 36 37 00 09 00 01 0f 05 b5 de + Marker |Module id |Ac|Cm|Size |Pl|Ix|Chksm| + */ + SSPMInitSend(); + memcpy(SspmBuffer +3, Sspm->module[module], SSPM_MODULE_NAME_SIZE); + SspmBuffer[16] = SSPM_FUNC_GET_MODULE_STATE; + SspmBuffer[18] = 0x01; + SspmBuffer[19] = 0x0F; // State of all four relays + Sspm->command_sequence++; + SspmBuffer[20] = Sspm->command_sequence; + + SSPMSend(23); +} + +void SSPMSendGetOps(uint32_t module) { + /* + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 + aa 55 01 6b 7e 32 37 39 37 34 13 4b 35 36 37 00 04 00 00 08 c0 0a + Marker |Module id |Ac|Cm|Size |Ix|Chksm| + */ + SSPMInitSend(); + memcpy(SspmBuffer +3, Sspm->module[module], SSPM_MODULE_NAME_SIZE); + SspmBuffer[16] = SSPM_FUNC_GET_OPS; + Sspm->command_sequence++; + SspmBuffer[19] = Sspm->command_sequence; + + SSPMSend(22); +} + +void SSPMSendGetScheme(uint32_t module) { + /* + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 + AA 55 01 6b 7e 32 37 39 37 34 13 4b 35 36 37 00 0b 00 00 09 14 c8 + Marker |Module id |Ac|Cm|Size |Ix|Chksm| + */ + SSPMInitSend(); + memcpy(SspmBuffer +3, Sspm->module[module], SSPM_MODULE_NAME_SIZE); + SspmBuffer[16] = SSPM_FUNC_GET_SCHEME; + Sspm->command_sequence++; + SspmBuffer[19] = Sspm->command_sequence; + + SSPMSend(22); +} + +void SSPMSendGetEnergy(uint32_t relay) { + /* + relay_num = 1..8 + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 18 00 10 6b 7e 32 37 39 37 34 13 4b 35 36 37 01 01 00 3c 2a db d1 + */ + uint8_t module = relay >> 2; + uint8_t channel = 1 << (relay & 0x03); // Channel relays are bit masked + SSPMInitSend(); + SspmBuffer[16] = SSPM_FUNC_GET_ENERGY; + SspmBuffer[18] = 0x10; + memcpy(SspmBuffer +19, Sspm->module[module], SSPM_MODULE_NAME_SIZE); + SspmBuffer[31] = 0x01; + SspmBuffer[32] = channel; + SspmBuffer[33] = 0; + SspmBuffer[34] = 0x3C; + Sspm->command_sequence++; + SspmBuffer[35] = Sspm->command_sequence; + + SSPMSend(38); +} + +void SSPMSendGetEnergyTotal(uint32_t relay) { + /* + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 16 00 0d 6b 7e 32 37 39 37 34 13 4b 35 36 37 01 14 e6 93 + */ + uint8_t module = relay >> 2; + uint8_t channel = relay & 0x03; // Channel relays are NOT bit masked this time + SSPMInitSend(); + SspmBuffer[16] = SSPM_FUNC_GET_ENERGY_TOTAL; + SspmBuffer[18] = 0x0D; + memcpy(SspmBuffer +19, Sspm->module[module], SSPM_MODULE_NAME_SIZE); + SspmBuffer[31] = channel; + Sspm->command_sequence++; + SspmBuffer[32] = Sspm->command_sequence; + + SSPMSend(35); +} + +void SSPMSendGetLog(uint32_t relay, uint32_t entries) { + /* + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 1a 00 10 6b 7e 32 37 39 37 34 13 4b 35 36 37 00 00 00 1d 09 8c cd + */ + uint8_t module = relay >> 2; + SSPMInitSend(); + SspmBuffer[16] = SSPM_FUNC_GET_LOG; + SspmBuffer[18] = 0x10; + memcpy(SspmBuffer +19, Sspm->module[module], SSPM_MODULE_NAME_SIZE); + SspmBuffer[31] = 0; + SspmBuffer[32] = 0; + SspmBuffer[33] = 0; + SspmBuffer[34] = entries; // Number of logs + Sspm->command_sequence++; + SspmBuffer[35] = Sspm->command_sequence; + + SSPMSend(38); +} + +void SSPMSendAck(uint32_t command_sequence) { + /* + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 80 0f 00 01 00 01 3d e6 + Marker |Module id |Ac|Cm|Size |Pl|Ix|Chksm| + */ + SspmBuffer[15] = 0x80; + SspmBuffer[17] = 0x00; + SspmBuffer[18] = 0x01; + SspmBuffer[19] = 0x00; + SspmBuffer[20] = command_sequence; + + SSPMSend(23); +} + +void SSPMHandleReceivedData(void) { + uint8_t command = SspmBuffer[16]; + bool ack = (0x80 == SspmBuffer[15]); + uint8_t command_sequence = SspmBuffer[19 + Sspm->expected_bytes]; + +// AddLog(LOG_LEVEL_DEBUG, PSTR("SPM: Rcvd ack %d, cmnd %d, seq %d, size %d"), +// ack, command, command_sequence, Sspm->expected_bytes); + + if (ack) { + // Responses from ARM (Acked) + switch(command) { + case SSPM_FUNC_FIND: + /* 0x00 + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 01 00 00 fc 73 + |Er| |St| + */ + if ((1 == Sspm->expected_bytes) && (0 == SspmBuffer[19])) { + Sspm->init_step++; + } + break; + case SSPM_FUNC_GET_OPS: + /* 0x04 - Overload Protection + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 + AA 55 01 8b 34 32 37 39 37 34 13 4b 35 36 37 80 04 00 02 00 00 06 98 06 + Marker |Module id |Ac|Cm|Size | |Ch|Ra|Max P |Min P |Max U |Min U |Max I |De|Ix|Chksm| + | | | 4400W| 0.1W| 240V| 0.1V| 20A| | + AA 55 01 6B 7E 32 37 39 37 34 13 4B 35 36 37 80 04 00 35 00 07 00 11 30 00 00 00 0A 00 F0 00 00 00 0A 00 14 00 00 + 00 11 30 00 00 00 0A 00 F0 00 00 00 0A 00 14 00 00 + 00 11 30 00 00 00 0A 00 F0 00 00 00 0A 00 14 00 00 07 8A 86 + */ + if (0x02 == Sspm->expected_bytes) { + + } + + Sspm->module_selected--; + if (Sspm->module_selected > 0) { + SSPMSendGetModuleState(Sspm->module_selected -1); + } else { + SSPMSendGetScheme(Sspm->module_selected); + } + break; + case SSPM_FUNC_GET_MODULE_STATE: + /* 0x09 + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 + AA 55 01 8b 34 32 37 39 37 34 13 4b 35 36 37 80 09 00 06 00 0f 01 01 01 01 05 fe 35 + |OS|4RelayMasks| + */ + if (0x06 == Sspm->expected_bytes) { + // SspmBuffer[20] & 0x0F // Relays operational + power_t current_state = SspmBuffer[20] >> 4; // Relays state + power_t mask = 0x0000000F; + for (uint32_t i = 0; i < Sspm->module_max; i++) { + if ((SspmBuffer[3] == Sspm->module[i][0]) && (SspmBuffer[4] == Sspm->module[i][1])) { + current_state <<= (i * 4); + mask <<= (i * 4); + TasmotaGlobal.power &= (POWER_MASK ^ mask); + TasmotaGlobal.power |= current_state; + break; + } + } + Sspm->old_power = TasmotaGlobal.power; + TasmotaGlobal.devices_present += 4; + } + SSPMSendGetOps(Sspm->module_selected -1); + break; + case SSPM_FUNC_GET_SCHEME: + /* 0x0B + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 + AA 55 01 6b 7e 32 37 39 37 34 13 4b 35 36 37 80 0b 00 02 00 00 09 bb c7 + |?? ??| + */ + if (0x02 == Sspm->expected_bytes) { + + } + Sspm->module_selected++; + if (Sspm->module_selected < Sspm->module_max) { + SSPMSendGetScheme(Sspm->module_selected); + } else { + AddLog(LOG_LEVEL_DEBUG, PSTR("SPM: Relay scan done")); + + Sspm->init_step = SPM_DEVICES_FOUND; +// Sspm->get_energy_relay = 1; +// Sspm->allow_updates = 1; // Enable requests from 100mSec loop + } + break; + case SSPM_FUNC_SET_TIME: + /* 0x0C + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 80 0c 00 01 00 04 3e 62 + */ + SSPMSendGetModuleState(Sspm->module_selected -1); + break; + case SSPM_FUNC_INIT_SCAN: + /* 0x10 + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 + AA 55 01 ff ff ff ff ff ff ff ff ff ff ff ff 80 10 00 01 00 02 e5 03 + */ + Sspm->module_max = 0; + break; + case SSPM_FUNC_UNITS: + /* 0x15 + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 80 15 00 04 00 01 00 00 01 81 b1 + |?? ?? ?? ??| + */ + SSPMSendInitScan(); + break; + case SSPM_FUNC_GET_ENERGY_TOTAL: + /* 0x16 + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 80 16 01 7e 00 8b 34 32 37 39 37 34 13 4b 35 36 37 + 03 <- L4 + 07 e5 0b 0d <- End date (Today) 2021 nov 13 + 07 e5 05 11 <- Start date 2021 may 17 + 00 05 <- 5kWh (13/11 Today) + 00 00 <- 0 (12/11 Yesterday) + 00 04 <- 4kWh (11/11 etc) + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 42 67 46 + */ + { + uint32_t total_energy = 0; + uint32_t entries = (Sspm->expected_bytes - 22) / 2; + for (uint32_t i = 0; i < entries; i++) { + total_energy += (SspmBuffer[41 + (i*2)] << 8) + SspmBuffer[42 + (i*2)]; + } + uint32_t channel = SspmBuffer[32]; + for (uint32_t module = 0; module < Sspm->module_max; module++) { + if ((SspmBuffer[20] == Sspm->module[module][0]) && (SspmBuffer[21] == Sspm->module[module][1])) { + Sspm->total[module][channel] = total_energy; // xkWh + break; + } + } + Sspm->allow_updates = 1; + } + break; + case SSPM_FUNC_ENERGY_PERIOD: + /* 0x1B + Response after start energy period + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 80 1b 00 0e [00] 8b 34 32 37 39 37 34 13 4b 35 36 37 [03] f7 b1 bc L4 + Response after refresh or stop energy period + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 80 1b 00 11 [00] 8b 34 32 37 39 37 34 13 4b 35 36 37 [03] [00 00 00] f8 94 15 L4, kWh start period (0) + */ + + break; + } + } else { + // Initiated by ARM + switch(command) { + case SSPM_FUNC_ENERGY_RESULT: + /* 0x06 + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 06 00 1c 6b 7e 32 37 39 37 34 13 4b 35 36 37 01 00 00 00 e3 5b 00 00 00 00 00 00 00 00 00 6b 1f 95 1e + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 06 00 1C 8B 34 32 37 39 37 34 13 4B 35 36 37 01 00 0B 00 E4 37 00 19 0E 00 00 02 00 19 09 4B 28 1D 71 + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 06 00 1C 8B 34 32 37 39 37 34 13 4B 35 36 37 08 00 0A 00 E3 61 00 18 2E 00 00 00 00 18 33 4B 27 D3 0D + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 06 00 1C 8B 34 32 37 39 37 34 13 4B 35 36 37 08 02 04 00 DC 14 01 C1 3D 00 10 19 01 C2 29 4B 37 6B 26 + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 06 00 1c 8b 34 32 37 39 37 34 13 4b 35 36 37 08 00 44 00 e1 35 00 9a 3e 00 01 45 00 9a 38 00 08 8b ae + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 06 00 1c 8b 34 32 37 39 37 34 13 4b 35 36 37 08 00 4a 00 e1 22 00 61 4d 00 2c 38 00 a8 28 20 26 21 70 + |Ch|Curre|Voltage |ActivePo|Reactive|Apparent|??| + Values are XX XX - number + XX - decimals + + + + Curr Voltag Active Reacti Appare + 0 1 2 3 4 5 6 7 8 910111213141516171819202122232425262728293031 3233 343536 373839 404142 434445 46 47 4849 + AA55010000000000000000000000000006001C8B343237393734134B35363708 000A 00E05B 001817 00013B 001825 4B BC 3DDA 0.100A 224.91V 24.23W <-- 25W bulb + AA55010000000000000000000000000006001C8B343237393734134B35363708 000A 00E115 00181A 00013D 001823 4B BE 6209 + AA55010000000000000000000000000006001C8B343237393734134B35363708 0044 00E260 009C1C 000000 009C1B 00 36 FD69 0.680A 226.96V 156.28W <-- 150W bulb + + AA55010000000000000000000000000006001C8B343237393734134B35363708 0054 00E134 007525 00220A 00BD5D 20 34 55D6 + AA55010000000000000000000000000006001C8B343237393734134B35363708 0054 00E10A 007519 002126 00BD27 20 36 77EA + AA55010000000000000000000000000006001C8B343237393734134B35363708 0053 00DE40 00731F 001604 00B952 4B 12 9255 + + AA55010000000000000000000000000006001C8B343237393734134B35363708 075B 00D502 06940F 001863 069830 4B 1C E0DE + + AA55010000000000000000000000000006001c8b343237393734134b35363708 0044 00e025 009920 00010f 00993b 00 b3 07 a2 0.68A 223.25V 152.66W 0.54 Rea 152.5 Schijn + + + */ + { + uint32_t channel = 0; + for (channel = 0; channel < 4; channel++) { + if (SspmBuffer[31] & 1) { break; } + SspmBuffer[31] >>= 1; + } + for (uint32_t module = 0; module < Sspm->module_max; module++) { + if ((SspmBuffer[19] == Sspm->module[module][0]) && (SspmBuffer[20] == Sspm->module[module][1])) { + Sspm->current[module][channel] = SspmBuffer[32] + (float)SspmBuffer[33] / 100; // x.xxA + Sspm->voltage[module][channel] = (SspmBuffer[34] << 8) + SspmBuffer[35] + (float)SspmBuffer[36] / 100; // x.xxV + Sspm->active_power[module][channel] = (SspmBuffer[37] << 8) + SspmBuffer[38] + (float)SspmBuffer[39] / 100; // x.xxW + Sspm->reactive_power[module][channel] = (SspmBuffer[40] << 8) + SspmBuffer[41] + (float)SspmBuffer[42] / 100; // x.xxVAr + Sspm->apparent_power[module][channel] = (SspmBuffer[43] << 8) + SspmBuffer[44] + (float)SspmBuffer[45] / 100; // x.xxVA + break; + } + } + SSPMSendAck(command_sequence); + Sspm->allow_updates = 1; + } + break; + case SSPM_FUNC_KEY_PRESS: + /* 0x07 + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 07 00 0d 6b 7e 32 37 39 37 34 13 4b 35 36 37 11 04 bf c3 + |AS| + */ + if (!Sspm->no_send_key) { + power_t relay = SspmBuffer[31] & 0x0F; // Relays active + power_t relay_state = SspmBuffer[31] >> 4; // Relays state + for (uint32_t i = 0; i < Sspm->module_max; i++) { + if ((SspmBuffer[19] == Sspm->module[i][0]) && (SspmBuffer[20] == Sspm->module[i][1])) { + relay <<= (i * 4); + relay_state <<= (i * 4); + break; + } + } + for (uint32_t i = 1; i <= TasmotaGlobal.devices_present; i++) { + if (relay &1) { + ExecuteCommandPower(i, relay_state &1, SRC_BUTTON); + } + relay >>= 1; + relay_state >>= 1; + } + Sspm->old_power = TasmotaGlobal.power; + } + SSPMSendAck(command_sequence); + break; + case SSPM_FUNC_SCAN_START: + /* 0x0F + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 0f 00 01 02 01 9d f8 + */ +// Sspm->module_max = 0; + SSPMSendAck(command_sequence); + break; + case SSPM_FUNC_SCAN_RESULT: + /* 0x13 + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 13 00 24 6b 7e 32 37 39 37 34 13 4b 35 36 37 04 00 00 00 82 01 00 00 14 00 00 0a 00 f0 00 00 00 0a 11 30 00 00 00 0a 02 8f cd + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 13 00 24 8b 34 32 37 39 37 34 13 4b 35 36 37 04 00 00 00 82 01 00 00 14 00 00 0a 00 f0 00 00 00 0a 11 30 00 00 00 0a 02 a0 6f + */ + if ((0x24 == Sspm->expected_bytes) && (Sspm->module_max < SSPM_MAX_MODULES)) { + memcpy(Sspm->module[1], Sspm->module[0], (SSPM_MAX_MODULES -1) * SSPM_MODULE_NAME_SIZE); + memcpy(Sspm->module[0], SspmBuffer + 19, SSPM_MODULE_NAME_SIZE); + Sspm->module_max++; + } + SSPMSendAck(command_sequence); + break; + case SSPM_FUNC_SCAN_DONE: + /* 0x19 + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 19 00 00 03 a1 16 + */ + SSPMSendAck(command_sequence); + Sspm->module_selected = Sspm->module_max; + SSPMSendSetTime(); + break; + } + } +} + +void SSPMSerialInput(void) { + /* + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 19 00 00 03 a1 16 + Marker |Module id |Ac|Cm|Size |Ix|Chksm| + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 01 00 00 fc 73 + Marker |Module id |Ac|Cm|Size |Pl|Ix|Chksm| + AA 55 01 6b 7e 32 37 39 37 34 13 4b 35 36 37 80 09 00 06 00 0f 01 01 01 01 05 f9 9d + Marker |Module id |Ac|Cm|Size |Payload |Ix|Chksm| + 00 Request + 80 Response (Ack) + */ + while (SspmSerial->available()) { + yield(); + uint8_t serial_in_byte = SspmSerial->read(); + + if ((0x55 == serial_in_byte) && (0xAA == SspmBuffer[Sspm->serial_in_byte_counter -1])) { + Sspm->expected_bytes = 0; + SspmBuffer[0] = 0xAA; + Sspm->serial_in_byte_counter = 1; + } + if (Sspm->serial_in_byte_counter < SSPM_SERIAL_BUFFER_SIZE -1) { + SspmBuffer[Sspm->serial_in_byte_counter++] = serial_in_byte; + if (19 == Sspm->serial_in_byte_counter) { + Sspm->expected_bytes = (SspmBuffer[Sspm->serial_in_byte_counter -2] << 8) + SspmBuffer[Sspm->serial_in_byte_counter -1]; + } + if (Sspm->serial_in_byte_counter == (22 + Sspm->expected_bytes)) { + + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SPM: ARM %*_H"), Sspm->serial_in_byte_counter, SspmBuffer); + + uint16_t crc_rcvd = (SspmBuffer[Sspm->serial_in_byte_counter -2] << 8) + SspmBuffer[Sspm->serial_in_byte_counter -1]; + uint16_t crc_calc = SSPMCalculateCRC(SspmBuffer, Sspm->serial_in_byte_counter -2); + if (crc_rcvd == crc_calc) { + SSPMHandleReceivedData(); + } else { + AddLog(LOG_LEVEL_DEBUG, PSTR("SPM: CRC error")); + } + Sspm->serial_in_byte_counter = 0; + Sspm->expected_bytes = 0; + } + } else { + AddLog(LOG_LEVEL_DEBUG, PSTR("SPM: Serial input buffer overflow")); + Sspm->serial_in_byte_counter = 0; + Sspm->expected_bytes = 0; + } + } +} + +void SSPMInit(void) { + if (!ValidTemplate(PSTR("Sonoff SPM (POC1)"))) { return; } + if (!PinUsed(GPIO_RXD) || !PinUsed(GPIO_TXD)) { return; } + + Sspm = (TSspm*)calloc(sizeof(TSspm), 1); + if (!Sspm) { return; } + SspmBuffer = (uint8_t*)malloc(SSPM_SERIAL_BUFFER_SIZE); + if (!SspmBuffer) { + free(Sspm); + return; + } + SspmSerial = new TasmotaSerial(Pin(GPIO_RXD), Pin(GPIO_TXD), 1, 0, SSPM_SERIAL_BUFFER_SIZE); + if (!SspmSerial->begin(115200)) { + free(SspmBuffer); + free(Sspm); + return; + } + + pinMode(SSPM_GPIO_ARM_RESET, OUTPUT); + digitalWrite(SSPM_GPIO_ARM_RESET, 1); + + if (0 == Settings->flag2.voltage_resolution) { + Settings->flag2.voltage_resolution = 1; // SPM has only 2 decimals + Settings->flag2.current_resolution = 2; // SPM has only 2 decimals + Settings->flag2.wattage_resolution = 2; // SPM has only 2 decimals + Settings->flag2.energy_resolution = 0; // SPM has no decimals on total energy + } + + Sspm->old_power = TasmotaGlobal.power; + Sspm->init_step = SPM_WAIT; // Start init sequence +} + +void SSPMEvery100ms(void) { + if (Sspm->no_send_key) { Sspm->no_send_key--; } + + if (Sspm->timeout) { + Sspm->timeout--; + if (!Sspm->timeout) { + Sspm->allow_updates = 1; + } + } + + // Fix race condition if the ARM doesn't respond + if ((Sspm->init_step > SPM_NONE) && (Sspm->init_step < SPM_SEND_FUNC_UNITS)) { + Sspm->counter++; + if (Sspm->counter > 20) { + Sspm->init_step = SPM_NONE; + } + } + switch (Sspm->init_step) { + case SPM_NONE: + return; + case SPM_WAIT: + Sspm->init_step++; + break; + case SPM_RESET: + // Reset ARM + digitalWrite(SSPM_GPIO_ARM_RESET, 0); + delay(18); + digitalWrite(SSPM_GPIO_ARM_RESET, 1); + delay(18); + Sspm->init_step++; + case SPM_POLL: + SSPMSendCmnd(SSPM_FUNC_FIND); + break; + case SPM_POLL_ACK: + SSPMSendCmnd(SSPM_FUNC_FIND); + break; + case SPM_SEND_FUNC_UNITS: + Sspm->init_step++; + SSPMSendCmnd(SSPM_FUNC_UNITS); + break; + case SPM_DEVICES_FOUND: + TasmotaGlobal.discovery_counter = 1; // force TasDiscovery() + Sspm->get_energy_relay = 1; + Sspm->allow_updates = 1; // Enable requests from 100mSec loop + Sspm->init_step++; + break; + case SPM_GET_ENERGY_TOTALS: + // Retrieve Energy total status from up to 128 relays + if (Sspm->allow_updates && (Sspm->get_energy_relay > 0)) { + SSPMSetLock(4); + SSPMSendGetEnergyTotal(Sspm->get_energy_relay -1); + Sspm->get_energy_relay++; + if (Sspm->get_energy_relay > TasmotaGlobal.devices_present) { + Sspm->get_energy_relay = 1; + Sspm->init_step++; + } + } + break; + case SPM_ALLOW_LOOP: + // Retrieve Energy status from up to 128 relays + if (Sspm->allow_updates && (Sspm->get_energy_relay > 0)) { + power_t powered_on = TasmotaGlobal.power >> (Sspm->get_energy_relay -1); + if (0 == Sspm->loop_step) { + // Get energy total only once in any 256 requests to safe comms + if (powered_on &1) { + SSPMSetLock(4); + SSPMSendGetEnergyTotal(Sspm->get_energy_relay -1); + } + Sspm->get_energy_relay++; + if (Sspm->get_energy_relay > TasmotaGlobal.devices_present) { + Sspm->get_energy_relay = 1; + Sspm->loop_step++; + } + } else { + if (powered_on &1) { + SSPMSetLock(4); + SSPMSendGetEnergy(Sspm->get_energy_relay -1); + } else { + uint32_t relay_set = (Sspm->get_energy_relay -1) >> 2; + uint32_t relay_num = (Sspm->get_energy_relay -1) &3; + if (Sspm->voltage[relay_set][relay_num]) { + Sspm->voltage[relay_set][relay_num] = 0; + Sspm->current[relay_set][relay_num] = 0; + Sspm->active_power[relay_set][relay_num] = 0; + Sspm->apparent_power[relay_set][relay_num] = 0; + Sspm->reactive_power[relay_set][relay_num] = 0; + Sspm->power_factor[relay_set][relay_num] = 0; + } + } + Sspm->loop_step++; // Rolls over after 256 so allows for scanning at least all relays twice + Sspm->get_energy_relay++; + if ((Sspm->get_energy_relay > TasmotaGlobal.devices_present) || !Sspm->loop_step) { + Sspm->get_energy_relay = 1; + } + } + } + break; + } +} + +bool SSPMSetDevicePower(void) { + power_t new_power = XdrvMailbox.index; + if (new_power != Sspm->old_power) { + for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { + uint8_t new_state = (new_power >> i) &1; + if (new_state != ((Sspm->old_power >> i) &1)) { + SSPMSendSetRelay(i, new_state); + Sspm->no_send_key = 10; // Disable buttons for 10 * 0.1 second + } + } + Sspm->old_power = new_power; + } + return true; +} + +bool SSPMButton(void) { + bool result = false; + uint32_t button = XdrvMailbox.payload; + if ((PRESSED == button) && (NOT_PRESSED == Sspm->last_button)) { // Button pressed + SSPMSendInitScan(); + result = true; // Disable further button processing + } + Sspm->last_button = button; + return result; +} + +const char kSSPMEnergyPhases[] PROGMEM = "%*_f / %*_f / %*_f / %*_f|[%*_f,%*_f,%*_f,%*_f]"; + +char* SSPMEnergyFormat(char* result, float* input, uint32_t resolution, bool json) { + char layout[32]; + GetTextIndexed(layout, sizeof(layout), json, kSSPMEnergyPhases); + ext_snprintf_P(result, FLOATSZ * 4, layout, resolution, &input[0], resolution, &input[1], resolution, &input[2], resolution, &input[3]); + return result; +} + +const char HTTP_SSPMENERGY_SNS[] PROGMEM = + "{s}" D_POWERUSAGE_APPARENT "{m}%s " D_UNIT_VA "{e}" + "{s}" D_POWERUSAGE_REACTIVE "{m}%s " D_UNIT_VAR "{e}" + "{s}" D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; // {s} = , {m} = , {e} = + +void SSPMEnergyShow(bool json) { + if (!TasmotaGlobal.devices_present) { return; } // Not ready yet + + if (json) { + ResponseAppend_P(PSTR(",\"SPM\":{\"" D_JSON_TOTAL "\":[")); + for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { + ResponseAppend_P(PSTR("%s%*_f"), (i>0)?",":"", 0, &Sspm->total[i >>2][i &3]); + } + ResponseAppend_P(PSTR("],\"" D_JSON_POWERUSAGE "\":[")); + for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { + ResponseAppend_P(PSTR("%s%*_f"), (i>0)?",":"", Settings->flag2.wattage_resolution, &Sspm->active_power[i >>2][i &3]); + } + ResponseAppend_P(PSTR("],\"" D_JSON_APPARENT_POWERUSAGE "\":[")); + for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { + ResponseAppend_P(PSTR("%s%*_f"), (i>0)?",":"", Settings->flag2.wattage_resolution, &Sspm->apparent_power[i >>2][i &3]); + } + ResponseAppend_P(PSTR("],\"" D_JSON_REACTIVE_POWERUSAGE "\":[")); + for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { + ResponseAppend_P(PSTR("%s%*_f"), (i>0)?",":"", Settings->flag2.wattage_resolution, &Sspm->reactive_power[i >>2][i &3]); + } + ResponseAppend_P(PSTR("],\"" D_JSON_VOLTAGE "\":[")); + for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { + ResponseAppend_P(PSTR("%s%*_f"), (i>0)?",":"", Settings->flag2.voltage_resolution, &Sspm->voltage[i >>2][i &3]); + } + ResponseAppend_P(PSTR("],\"" D_JSON_CURRENT "\":[")); + for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { + ResponseAppend_P(PSTR("%s%*_f"), (i>0)?",":"", Settings->flag2.current_resolution, &Sspm->current[i >>2][i &3]); + } + ResponseAppend_P(PSTR("]}")); + } else { + Sspm->rotate++; + if ((Sspm->rotate >> 2) == Sspm->module_max) { + Sspm->rotate = 0; + } + + uint32_t module = Sspm->rotate >> 2; + uint32_t relay_base = module * 4; + WSContentSend_P(PSTR("{s}" D_SENSOR_RELAY "{m}L%02d / L%02d / L%02d / L%02d{e}"), relay_base +1, relay_base +2, relay_base +3, relay_base +4); + char value_chr[FLOATSZ * 4]; + WSContentSend_PD(HTTP_SNS_VOLTAGE, SSPMEnergyFormat(value_chr, Sspm->voltage[module], Settings->flag2.voltage_resolution, json)); + WSContentSend_PD(HTTP_SNS_CURRENT, SSPMEnergyFormat(value_chr, Sspm->current[module], Settings->flag2.current_resolution, json)); + WSContentSend_PD(HTTP_SNS_POWER, SSPMEnergyFormat(value_chr, Sspm->active_power[module], Settings->flag2.wattage_resolution, json)); + char valu2_chr[FLOATSZ * 4]; + char valu3_chr[FLOATSZ * 4]; + WSContentSend_PD(HTTP_SSPMENERGY_SNS, SSPMEnergyFormat(value_chr, Sspm->apparent_power[module], Settings->flag2.wattage_resolution, json), + SSPMEnergyFormat(valu2_chr, Sspm->reactive_power[module], Settings->flag2.wattage_resolution, json), + SSPMEnergyFormat(valu3_chr, Sspm->total[module], Settings->flag2.energy_resolution, json)); + } +} + +/*********************************************************************************************\ + * Commands +\*********************************************************************************************/ + +const char kSSPMCommands[] PROGMEM = "SSPM|" // Prefix + "Log|Energy|History|Scan" ; + +void (* const SSPMCommand[])(void) PROGMEM = { + &CmndSSPMLog, &CmndSSPMEnergy, &CmndSSPMEnergyHistory, &CmndSSPMScan }; + +void CmndSSPMLog(void) { + if ((XdrvMailbox.index < 1) || (XdrvMailbox.index > TasmotaGlobal.devices_present)) { XdrvMailbox.index = 1; } + XdrvMailbox.payload &= 0x1F; // Max 32 entries + SSPMSendGetLog(XdrvMailbox.index -1, XdrvMailbox.payload +1); + + ResponseCmndDone(); +} + +void CmndSSPMEnergy(void) { + if ((XdrvMailbox.index < 1) || (XdrvMailbox.index > TasmotaGlobal.devices_present)) { XdrvMailbox.index = 1; } + SSPMSendGetEnergy(XdrvMailbox.index -1); + + ResponseCmndDone(); +} + +void CmndSSPMEnergyHistory(void) { + if ((XdrvMailbox.index < 1) || (XdrvMailbox.index > TasmotaGlobal.devices_present)) { XdrvMailbox.index = 1; } + SSPMSendGetEnergyTotal(XdrvMailbox.index -1); + + ResponseCmndDone(); +} + +void CmndSSPMScan(void) { + SSPMSendInitScan(); + + ResponseCmndDone(); +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xdrv86(uint8_t function) +{ + bool result = false; + + if (FUNC_INIT == function) { + SSPMInit(); + } + else if (Sspm) { + switch (function) { + case FUNC_LOOP: + if (SspmSerial) { SSPMSerialInput(); } + break; + case FUNC_EVERY_100_MSECOND: + SSPMEvery100ms(); + break; + case FUNC_SET_DEVICE_POWER: + result = SSPMSetDevicePower(); + break; + case FUNC_EVERY_SECOND: + break; + case FUNC_JSON_APPEND: + SSPMEnergyShow(true); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + SSPMEnergyShow(false); + break; +#endif // USE_WEBSERVER + case FUNC_COMMAND: + result = DecodeCommand(kSSPMCommands, SSPMCommand); + break; + case FUNC_BUTTON_PRESSED: + result = SSPMButton(); + break; + } + } + return result; +} + +#endif // USE_SONOFF_SPM +#endif // ESP32 From f3c235b8e9872204d51a30dd40b7accd7f18e2e2 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Wed, 17 Nov 2021 22:48:48 +0100 Subject: [PATCH 059/185] Removed ILI9488 driver in favor of Unversal Display Driver --- BUILDS.md | 1 - CHANGELOG.md | 1 + .../JaretBurkett_ILI9488-gemu-1.0/ILI9488.cpp | 1164 ----------------- .../JaretBurkett_ILI9488-gemu-1.0/ILI9488.h | 174 --- .../JaretBurkett_ILI9488-gemu-1.0/README.md | 8 - .../examples/graphicstest/graphicstest.ino | 350 ----- .../keywords.txt | 30 - .../library.properties | 9 - .../spi_register.h | 189 --- tasmota/my_user_config.h | 1 - tasmota/support_features.ino | 6 +- tasmota/tasmota_configurations.h | 2 +- tasmota/xdrv_13_display.ino | 2 +- tasmota/xdrv_52_3_berry_display.ino | 2 +- tasmota/xdsp_08_ILI9488.ino | 167 --- tasmota/xdsp_08_ILI9488_UD.ino | 111 -- tasmota/xdsp_17_universal.ino | 25 +- 17 files changed, 19 insertions(+), 2223 deletions(-) delete mode 100644 lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/ILI9488.cpp delete mode 100644 lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/ILI9488.h delete mode 100644 lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/README.md delete mode 100644 lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/examples/graphicstest/graphicstest.ino delete mode 100644 lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/keywords.txt delete mode 100644 lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/library.properties delete mode 100644 lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/spi_register.h delete mode 100644 tasmota/xdsp_08_ILI9488.ino delete mode 100644 tasmota/xdsp_08_ILI9488_UD.ino diff --git a/BUILDS.md b/BUILDS.md index 4a55f1498..483ac04c8 100644 --- a/BUILDS.md +++ b/BUILDS.md @@ -218,7 +218,6 @@ m = minimal, l = lite, t = tasmota, k = knx, s = sensors, i = ir, d = display | USE_DISPLAY_ILI9341 | - | - | - / - | - | - | - | x | | USE_DISPLAY_EPAPER_29 | - | - | - / - | - | - | - | x | | USE_DISPLAY_EPAPER_42 | - | - | - / - | - | - | - | x | -| USE_DISPLAY_ILI9488 | - | - | - / - | - | - | - | x | | USE_DISPLAY_SSD1351 | - | - | - / - | - | - | - | x | | USE_DISPLAY_RA8876 | - | - | - / - | - | - | - | x | | USE_DISPLAY_ST7789 | - | - | - / - | - | - | - | x | diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d3711803..98b1365fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file. ### Changed - ESP8266 Gratuitous ARP enabled and set to 60 seconds (#13623) +- Removed ILI9488 driver in favor of Unversal Display Driver ## [10.0.0.2] 20211113 ### Added diff --git a/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/ILI9488.cpp b/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/ILI9488.cpp deleted file mode 100644 index 8b801feb1..000000000 --- a/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/ILI9488.cpp +++ /dev/null @@ -1,1164 +0,0 @@ -/*************************************************** - STM32 Support added by Jaret Burkett at OSHlab.com - - This is our library for the Adafruit ILI9488 Breakout and Shield - ----> http://www.adafruit.com/products/1651 - - Check out the links above for our tutorials and wiring diagrams - These displays use SPI to communicate, 4 or 5 pins are required to - interface (RST is optional) - Adafruit invests time and resources providing this open source code, - please support Adafruit and open-source hardware by purchasing - products from Adafruit! - - Written by Limor Fried/Ladyada for Adafruit Industries. - MIT license, all text above must be included in any redistribution - ****************************************************/ -#include -#include "ILI9488.h" -#include - -// if using software spi this optimizes the code - -#ifdef ESP32 -#define ILI9488_DIMMER -#undef ESP32_PWM_CHANNEL -#define ESP32_PWM_CHANNEL 1 -#endif - -#define ILI9488_START start(); -#define ILI9488_STOP stop(); - -const uint16_t ili9488_colors[]={ILI9488_BLACK,ILI9488_WHITE,ILI9488_RED,ILI9488_GREEN,ILI9488_BLUE,ILI9488_CYAN,ILI9488_MAGENTA,\ - ILI9488_YELLOW,ILI9488_NAVY,ILI9488_DARKGREEN,ILI9488_DARKCYAN,ILI9488_MAROON,ILI9488_PURPLE,ILI9488_OLIVE,\ -ILI9488_LIGHTGREY,ILI9488_DARKGREY,ILI9488_ORANGE,ILI9488_GREENYELLOW,ILI9488_PINK}; - -// Constructor when using software SPI. All output pins are configurable. -ILI9488::ILI9488(int8_t cs,int8_t mosi,int8_t sclk,int8_t bp) : Renderer(ILI9488_TFTWIDTH, ILI9488_TFTHEIGHT) { - _cs = cs; - _mosi = mosi; - _sclk = sclk; - _bp = bp; - _hwspi = 0; -} - -/* - -CPU Clock = 80 Mhz -max clock of display is 15 Mhz (66ns sclk cycle) -so cpu/8 => 10 Mhz should be ok - -HSPI CLK 5 GPIO14 -HSPI /CS 8 GPIO15 -HSPI MOSI 7 GPIO13 -HSPI MISO 6 GPIO12 - - -GPIO names for your easy reference: -GPIO0: PERIPHS_IO_MUX_GPIO0_U -GPIO1: PERIPHS_IO_MUX_U0TXD_U -GPIO2: PERIPHS_IO_MUX_GPIO2_U -GPIO3: PERIPHS_IO_MUX_U0RXD_U -GPIO4: PERIPHS_IO_MUX_GPIO4_U -GPIO5: PERIPHS_IO_MUX_GPIO5_U -GPIO6: PERIPHS_IO_MUX_SD_CLK_U -GPIO7: PERIPHS_IO_MUX_SD_DATA0_U -GPIO8: PERIPHS_IO_MUX_SD_DATA1_U -GPIO9: PERIPHS_IO_MUX_SD_DATA2_U -GPIO10: PERIPHS_IO_MUX_SD_DATA3_U -GPIO11: PERIPHS_IO_MUX_SD_CMD_U -GPIO12: PERIPHS_IO_MUX_MTDI_U -GPIO13: PERIPHS_IO_MUX_MTCK_U -GPIO14: PERIPHS_IO_MUX_MTMS_U -GPIO15: PERIPHS_IO_MUX_MTDO_U -*/ - -uint8_t ili9488_start; - -#ifndef ESP32 -// ESP8266 -#include "spi_register.h" -#define SWSPI_OPTMODE -// this enables the 27 bit packed mode -#define RGB_PACK_MODE - -uint32_t ili9488_clock; -uint32_t ili9488_usr; -uint32_t ili9488_usr1; -uint32_t ili9488_usr2; -uint32_t ili9488_spi1c; -uint32_t ili9488_spi1c1; -uint32_t ili9488_spi1p; -uint32_t ili9488_gpmux; -uint32_t ili9488_mtdo; - - -uint32_t ili9488_clock_prev; -uint32_t ili9488_usr_prev; -uint32_t ili9488_usr1_prev; -uint32_t ili9488_usr2_prev; -uint32_t ili9488_spi1c_prev; -uint32_t ili9488_spi1c1_prev; -uint32_t ili9488_spi1p_prev; -uint32_t ili9488_gpmux_prev; -uint32_t ili9488_mtdo_prev; - -// code from espressif SDK -/****************************************************************************** - * FunctionName : spi_lcd_mode_init - * Description : SPI master initial function for driving LCD 3 wire spi -*******************************************************************************/ -void ILI9488::spi_lcd_mode_init(void) { - - ili9488_clock_prev=SPI1CLK; - ili9488_usr_prev=SPI1U; - ili9488_usr1_prev=SPI1U1; - ili9488_usr2_prev=SPI1U2; - ili9488_spi1c_prev=SPI1C; - ili9488_spi1c1_prev=SPI1C1; - ili9488_spi1p_prev=SPI1P; - ili9488_gpmux_prev=GPMUX; - ili9488_mtdo_prev=READ_PERI_REG(PERIPHS_IO_MUX_MTDO_U); - - SPI1U = SPIUMOSI | SPIUDUPLEX | SPIUSSE; - SPI1U1=0; - SPI1C = 0; - SPI1C1 = 0; - - //bit9 of PERIPHS_IO_MUX should be cleared when HSPI clock doesn't equal CPU clock - //bit8 of PERIPHS_IO_MUX should be cleared when SPI clock doesn't equal CPU clock - - WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105); //clear bit9 - //PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2);//configure miso to spi mode - PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);//configure mosi to spi mode - PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);//configure sclk to spi mode - PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);//configure cs to spi mode - -// the current implementation leaves about 1 us between transfers ???? -// due to lack of documentation i could not find the reason -// skipping this would double the speed !!! - - //SET_PERI_REG_MASK(SPI_USER(1), SPI_CS_SETUP|SPI_CS_HOLD|SPI_USR_COMMAND); - - SET_PERI_REG_MASK(SPI_USER(1), SPI_USR_COMMAND); - - CLEAR_PERI_REG_MASK(SPI_USER(1), SPI_FLASH_MODE); - // SPI clock=CPU clock/8 => 10 Mhz - /* - WRITE_PERI_REG(SPI_CLOCK(1), - ((1&SPI_CLKDIV_PRE)<>1)&0x7f; - - ILI9488_START - - regvalue= ((8&SPI_USR_COMMAND_BITLEN)<>1)|0x80; - - ILI9488_START - - regvalue= ((8&SPI_USR_COMMAND_BITLEN)<>= 1) { - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); - if(d&bit) WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); - else WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_mosi); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); - } - WRITE_PERI_REG( PIN_OUT_SET, 1<<_cs); -} -#else -// ESP32 section -void ILI9488::writedata(uint8_t d) { - ILI9488_START - fastSPIwrite(d,1); -} - -void ILI9488::writecommand(uint8_t c) { - ILI9488_START - fastSPIwrite(c,0); -} - -#include "soc/spi_reg.h" -#include "soc/spi_struct.h" -#include "esp32-hal-spi.h" -#include "esp32-hal.h" -#include "soc/spi_struct.h" - -#define RGB_PACK_MODE - -// since ardunio transferBits ia completely disfunctional -// we use our own hardware driver for 9 bit spi -void ILI9488::fastSPIwrite(uint8_t d,uint8_t dc) { - digitalWrite( _cs, LOW); - - uint32_t regvalue=d>>1; - if (dc) regvalue|=0x80; - else regvalue&=0x7f; - if (d&1) regvalue|=0x8000; - - REG_SET_BIT(SPI_USER_REG(3), SPI_USR_MOSI); - REG_WRITE(SPI_MOSI_DLEN_REG(3), 9 - 1); - uint32_t *dp=(uint32_t*)SPI_W0_REG(3); - *dp=regvalue; - REG_SET_BIT(SPI_CMD_REG(3), SPI_USR); - while (REG_GET_FIELD(SPI_CMD_REG(3), SPI_USR)); - - digitalWrite( _cs, HIGH); -} - -SPISettings ili9488_spiSettings; - -void ILI9488::start(void) { - if (ili9488_start) return; - SPI.beginTransaction(ili9488_spiSettings); - ili9488_start=1; -} -void ILI9488::stop(void) { - if (!ili9488_start) return; - SPI.endTransaction(); - ili9488_start=0; -} -#endif - - -uint16_t ILI9488::GetColorFromIndex(uint8_t index) { - if (index>=sizeof(ili9488_colors)/2) index=0; - return ili9488_colors[index]; -} - -void ILI9488::DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font) { - setRotation(rot); - invertDisplay(false); - setTextWrap(false); // Allow text to run off edges - cp437(true); - setTextFont(font&3); - setTextSize(size&7); - setTextColor(ILI9488_WHITE,ILI9488_BLACK); - setCursor(0,0); - fillScreen(ILI9488_BLACK); - ILI9488_STOP -} - -void ILI9488::DisplayOnff(int8_t on) { - if (on) { - writecommand(ILI9488_DISPON); //Display on - - if (_bp>=0) { - #ifdef ILI9488_DIMMER - ledcWrite(ESP32_PWM_CHANNEL,dimmer); - #else - digitalWrite(_bp,HIGH); - #endif - /* - writecommand(ILI9488_WRCTRLD); - writedata(0x0c); - writecommand(ILI9488_CAPC9); - writedata(0x3f);*/ - } - } else { - writecommand(ILI9488_DISPOFF); - - if (_bp>=0) { -#ifdef ILI9488_DIMMER - ledcWrite(ESP32_PWM_CHANNEL,0); -#else - digitalWrite(_bp,LOW); -#endif - } - //writecommand(ILI9488_WRCTRLD); - //writedata(0x04); - - } - ILI9488_STOP -} - -// dimmer 0-100 -void ILI9488::dim(uint8_t dim) { - dimmer = dim; - if (dimmer>15) dimmer=15; - dimmer=((float)dimmer/15.0)*255.0; -#ifdef ESP32 - ledcWrite(ESP32_PWM_CHANNEL,dimmer); -#endif -} - -void ILI9488::begin(void) { - pinMode(_cs, OUTPUT); - digitalWrite(_cs,HIGH); - pinMode(_sclk, OUTPUT); - pinMode(_mosi, OUTPUT); - if (_bp>=0) { -#ifdef ILI9488_DIMMER - ledcSetup(ESP32_PWM_CHANNEL,4000,8); - ledcAttachPin(_bp,ESP32_PWM_CHANNEL); - ledcWrite(ESP32_PWM_CHANNEL,128); -#else - pinMode(_bp, OUTPUT); - digitalWrite(_bp,HIGH); -#endif - } - -#ifndef ESP32 - if ((_sclk==14) && (_mosi==13) && (_cs==15)) { - // we use hardware spi - SPI.begin(); - _hwspi=1; - spi_lcd_mode_init(); - } else { - // we must use software spi - _hwspi=0; - } -#else - SPI.begin(_sclk,-1,_mosi, -1); - ili9488_spiSettings = SPISettings(10000000, MSBFIRST, SPI_MODE3); - _hwspi=1; -#endif - - ILI9488_START - delay(1); - - writecommand(0xE0); - writedata(0x00); - writedata(0x03); - writedata(0x09); - writedata(0x08); - writedata(0x16); - writedata(0x0A); - writedata(0x3F); - writedata(0x78); - writedata(0x4C); - writedata(0x09); - writedata(0x0A); - writedata(0x08); - writedata(0x16); - writedata(0x1A); - writedata(0x0F); - - - writecommand(0XE1); - writedata(0x00); - writedata(0x16); - writedata(0x19); - writedata(0x03); - writedata(0x0F); - writedata(0x05); - writedata(0x32); - writedata(0x45); - writedata(0x46); - writedata(0x04); - writedata(0x0E); - writedata(0x0D); - writedata(0x35); - writedata(0x37); - writedata(0x0F); - - writecommand(0XC0); //Power Control 1 - writedata(0x17); //Vreg1out - writedata(0x15); //Verg2out - - writecommand(0xC1); //Power Control 2 - writedata(0x41); //VGH,VGL - - writecommand(0xC5); //Power Control 3 - writedata(0x00); - writedata(0x12); //Vcom - writedata(0x80); - - writecommand(0x36); //Memory Access - writedata(0x48); - - writecommand(0x3A); // Interface Pixel Format - writedata(0x66); //18 bit - - writecommand(0XB0); // Interface Mode Control - writedata(0x80); //SDO NOT USE - - writecommand(0xB1); //Frame rate - writedata(0xA0); //60Hz - - writecommand(0xB4); //Display Inversion Control - writedata(0x02); //2-dot - - writecommand(0XB6); //Display Function Control RGB/MCU Interface Control - writedata(0x02); //MCU - writedata(0x02); //Source,Gate scan dieection - - writecommand(0XE9); // Set Image Functio - writedata(0x00); // Disable 24 bit data - - writecommand(0xF7); // Adjust Control - writedata(0xA9); - writedata(0x51); - writedata(0x2C); - writedata(0x82); // D7 stream, loose - - writecommand(ILI9488_SLPOUT); //Exit Sleep - delay(120); - writecommand(ILI9488_DISPON); //Display on - - ILI9488_STOP -} -/* -void ILI9488::setScrollArea(uint16_t topFixedArea, uint16_t bottomFixedArea){ - writecommand(0x33); // Vertical scroll definition - writedata(topFixedArea >> 8); - writedata(topFixedArea); - writedata((_height - topFixedArea - bottomFixedArea) >> 8); - writedata(_height - topFixedArea - bottomFixedArea); - writedata(bottomFixedArea >> 8); - writedata(bottomFixedArea); - ILI9488_STOP -} -void ILI9488::scroll(uint16_t pixels){ - writecommand(0x37); // Vertical scrolling start address - writedata(pixels >> 8); - writedata(pixels); - ILI9488_STOP -}*/ - -void ILI9488::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { - if (!x0 && !y0 && !x1 && !y1) { - x0=0; - y0=0; - x1=_width; - y1=_height; - } - setAddrWindow_int(x0, y0, x1-1, y1-1); -} - -void ILI9488::setAddrWindow_int(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { -uint8_t flag=0; - - if (!x0 && !y0 && !x1 && !y1) { - x0=0; - y0=0; - x1=_width; - y1=_height; - flag=1; - } - - if (x1>_width) x1=_width; - if (y1>_height) y1=_height; - - writecommand(ILI9488_CASET); // Column addr set - writedata(x0 >> 8); - writedata(x0 & 0xFF); // XSTART - writedata(x1 >> 8); - writedata(x1 & 0xFF); // XEND - - writecommand(ILI9488_PASET); // Row addr set - writedata(y0>>8); - writedata(y0 &0xff); // YSTART - writedata(y1>>8); - writedata(y1 &0xff); // YEND - - writecommand(ILI9488_RAMWR); // write to RAM - if (flag) ILI9488_STOP -} - -/* -void ILI9488::drawImage(const uint8_t* img, uint16_t x, uint16_t y, uint16_t w, uint16_t h){ -return; - // rudimentary clipping (drawChar w/big text requires this) - if((x >= _width) || (y >= _height)) return; - if((x + w - 1) >= _width) w = _width - x; - if((y + h - 1) >= _height) h = _height - y; - - setAddrWindow(x, y, x+w-1, y+h-1); - - // uint8_t hi = color >> 8, lo = color; - - #if defined(USE_FAST_PINIO) && !defined (_VARIANT_ARDUINO_STM32_) - *dcport |= dcpinmask; - *csport &= ~cspinmask; - #else - digitalWrite(_dc, HIGH); - digitalWrite(_cs, LOW); - #endif - uint8_t linebuff[w*3+1]; - uint16_t pixels = w*h; - // uint16_t count = 0; - uint32_t count = 0; - for (uint16_t i = 0; i < h; i++) { - uint16_t pixcount = 0; - for (uint16_t o = 0; o < w; o++) { - uint8_t b1 = img[count]; - count++; - uint8_t b2 = img[count]; - count++; - uint16_t color = b1 << 8 | b2; - linebuff[pixcount] = (((color & 0xF800) >> 11)* 255) / 31; - pixcount++; - linebuff[pixcount] = (((color & 0x07E0) >> 5) * 255) / 63; - pixcount++; - linebuff[pixcount] = ((color & 0x001F)* 255) / 31; - pixcount++; - } // for row - #if defined (__STM32F1__) - SPI.dmaSend(linebuff, w*3); - #else - for(uint16_t b = 0; b < w*3; b++){ - spiwrite(linebuff[b]); - } - #endif - - }// for col - #if defined(USE_FAST_PINIO) && !defined (_VARIANT_ARDUINO_STM32_) - *csport |= cspinmask; - #else - digitalWrite(_cs, HIGH); - #endif - - if (hwSPI) spi_end(); -} -*/ - -void ILI9488::pushColor(uint16_t color) { - write16BitColor(color); - ILI9488_STOP -} - -#if 1 -void ILI9488::pushColors(uint16_t *data, uint16_t len, boolean first) { - uint16_t color; - uint8_t buff[len*3+1]; - uint16_t count = 0; - uint8_t lencount = len; - while(lencount--) { - color = *data++; - buff[count] = (((color & 0xF800) >> 11)* 255) / 31; - count++; - buff[count] = (((color & 0x07E0) >> 5) * 255) / 63; - count++; - buff[count] = ((color & 0x001F)* 255) / 31; - count++; - } - - for(uint16_t b = 0; b < len*3; b++){ - writedata(buff[b]); - } - - ILI9488_STOP - -} -#else - -void ILI9488::pushColors(uint16_t *data, uint8_t len, boolean first) { - uint16_t color; - - while (len--) { - write16BitColor(*data++); - } - ILI9488_STOP -} -#endif - -void ILI9488::write16BitColor(uint16_t color){ - // #if (__STM32F1__) - // uint8_t buff[4] = { - // (((color & 0xF800) >> 11)* 255) / 31, - // (((color & 0x07E0) >> 5) * 255) / 63, - // ((color & 0x001F)* 255) / 31 - // }; - // SPI.dmaSend(buff, 3); - // #else - uint8_t r = (color & 0xF800) >> 11; - uint8_t g = (color & 0x07E0) >> 5; - uint8_t b = color & 0x001F; - - r = (r * 255) / 31; - g = (g * 255) / 63; - b = (b * 255) / 31; - - #ifndef SWSPI_OPTMODE - writedata(r); - writedata(g); - writedata(b); - #else - if (_hwspi) { - writedata(r); - writedata(g); - writedata(b); - } else { - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_cs); - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); - - for(uint8_t bit = 0x80; bit; bit >>= 1) { - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); - if(r&bit) WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); - else WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_mosi); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); - } - - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); - - for(uint8_t bit = 0x80; bit; bit >>= 1) { - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); - if(g&bit) WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); - else WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_mosi); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); - } - - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); - - for(uint8_t bit = 0x80; bit; bit >>= 1) { - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); - if(b&bit) WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); - else WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_mosi); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); - } - WRITE_PERI_REG( PIN_OUT_SET, 1<<_cs); - } - - #endif - ILI9488_STOP -} - -void ILI9488::drawPixel(int16_t x, int16_t y, uint16_t color) { - - if((x < 0) ||(x >= _width) || (y < 0) || (y >= _height)) return; - - setAddrWindow_int(x,y,x+1,y+1); - write16BitColor(color); - ILI9488_STOP -} - -void ILI9488::drawFastVLine(int16_t x, int16_t y, int16_t h, - uint16_t color) { - - // Rudimentary clipping - if((x >= _width) || (y >= _height)) return; - - if((y+h-1) >= _height) - h = _height-y; - - setAddrWindow_int(x, y, x, y+h-1); - - uint8_t r = (color & 0xF800) >> 11; - uint8_t g = (color & 0x07E0) >> 5; - uint8_t b = color & 0x001F; - - r = (r * 255) / 31; - g = (g * 255) / 63; - b = (b * 255) / 31; - - while (h--) { - #ifndef SWSPI_OPTMODE - writedata(r); - writedata(g); - writedata(b); - #else - if (_hwspi) { - writedata(r); - writedata(g); - writedata(b); - } else { - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_cs); - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); - - for(uint8_t bit = 0x80; bit; bit >>= 1) { - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); - if(r&bit) WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); - else WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_mosi); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); - } - - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); - - for(uint8_t bit = 0x80; bit; bit >>= 1) { - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); - if(g&bit) WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); - else WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_mosi); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); - } - - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); - - for(uint8_t bit = 0x80; bit; bit >>= 1) { - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); - if(b&bit) WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); - else WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_mosi); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); - } - WRITE_PERI_REG( PIN_OUT_SET, 1<<_cs); - } - #endif - } - ILI9488_STOP -} - -void ILI9488::drawFastHLine(int16_t x, int16_t y, int16_t w, - uint16_t color) { - - // Rudimentary clipping - if((x >= _width) || (y >= _height)) return; - if((x+w-1) >= _width) w = _width-x; - - setAddrWindow_int(x, y, x+w-1, y); - - uint8_t r = (color & 0xF800) >> 11; - uint8_t g = (color & 0x07E0) >> 5; - uint8_t b = color & 0x001F; - - r = (r * 255) / 31; - g = (g * 255) / 63; - b = (b * 255) / 31; - - while (w--) { -#ifndef SWSPI_OPTMODE - writedata(r); - writedata(g); - writedata(b); -#else - if (_hwspi) { - writedata(r); - writedata(g); - writedata(b); - } else { - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_cs); - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); - - for(uint8_t bit = 0x80; bit; bit >>= 1) { - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); - if(r&bit) WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); - else WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_mosi); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); - } - - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); - - for(uint8_t bit = 0x80; bit; bit >>= 1) { - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); - if(g&bit) WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); - else WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_mosi); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); - } - - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); - - for(uint8_t bit = 0x80; bit; bit >>= 1) { - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); - if(b&bit) WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); - else WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_mosi); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); - } - WRITE_PERI_REG( PIN_OUT_SET, 1<<_cs); - } -#endif - } - ILI9488_STOP -} - -// this moves 460 kbytes -// now at 475 ms with 13,3 Mhz clock -void ILI9488::fillScreen(uint16_t color) { - //uint32_t time=millis(); - fillRect(0, 0, _width, _height, color); - //time=millis()-time; - //Serial.printf("time %d ms\n",time); - ILI9488_STOP -} - - -//#define WAIT_9BITS asm_nop_9bits(); -#define WAIT_9BITS -//#define WAIT_BEFORE while(*((uint32_t *)0x60000100)&SPI_USR); //waiting for spi module available -#define WAIT_SPI_READY while(READ_PERI_REG(SPI_CMD(1))&SPI_USR); - -//#define WAIT_SPI_READY - -//#define DIAG_PIN_SET WRITE_PERI_REG( PIN_OUT_SET, 1<<2); -//#define DIAG_PIN_CLR WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<2); -#define DIAG_PIN_SET -#define DIAG_PIN_CLR - -//#define WRITE_PERI_REG(addr, val) (*((volatile uint32_t *)ETS_UNCACHED_ADDR(addr))) = (uint32_t)(val) - - -// CMD 0x60000200-1*0x100 -// SPI_USER2 0x60000200-1*0x100 + 0x24 - -//#define WRITE_SPI_REG WRITE_PERI_REG(0x60000124, regvalue_r);SET_PERI_REG_MASK(0x60000100, SPI_USR); -// THIS TAKES 1 us => 80 cpu clock cycles !!!!!!!!!!!!!!!!!!!!!!!!!! -// probably the memw causes this delay -#define WRITE_SPI_REG(A) WRITE_PERI_REG(SPI_USER2(1), A); SET_PERI_REG_MASK(SPI_CMD(1), SPI_USR); - -//#define WRITE_SPI_REG(A) *((uint32_t *)0x60000124)=A; *((uint32_t *)0x60000100)|=SPI_USR; - -//#define WRITE_SPI_REG - - - -// extremely strange => if this code is merged into pack_rgb() the software crashes -// swap bytes -uint32_t ulswap(uint32_t data) { -union { - uint32_t l; - uint8_t b[4]; -} data_; - - data_.l = data; - // MSBFIRST Byte first - data = (data_.b[3] | (data_.b[2] << 8) | (data_.b[1] << 16) | (data_.b[0] << 24)); - return data; -} - -// pack RGB into uint32 -uint32_t pack_rgb(uint32_t r, uint32_t g, uint32_t b) { - uint32_t data; - data=r<<23; - data|=g<<14; - data|=b<<5; - data|=0b10000000010000000010000000000000; - return ulswap(data); -} - -#ifndef ESP32 -// fill a rectangle -void ILI9488::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) { - - ILI9488_START - // rudimentary clipping (drawChar w/big text requires this) - if((x >= _width) || (y >= _height)) return; - if((x + w - 1) >= _width) w = _width - x; - if((y + h - 1) >= _height) h = _height - y; - - setAddrWindow_int(x, y, x+w-1, y+h-1); - //ILI9488_START - - uint8_t r = (color & 0xF800) >> 11; - uint8_t g = (color & 0x07E0) >> 5; - uint8_t b = color & 0x001F; - - r = (r * 255) / 31; - g = (g * 255) / 63; - b = (b * 255) / 31; - - uint32_t regvalue_r,regvalue_g,regvalue_b; - uint32_t data; - - if (_hwspi) { - // precalculate the register values for rgb - -#ifndef RGB_PACK_MODE - uint8_t bytetemp; - bytetemp=(r>>1)|0x80; - regvalue_r= ((8&SPI_USR_COMMAND_BITLEN)<>1)|0x80; - regvalue_g= ((8&SPI_USR_COMMAND_BITLEN)<>1)|0x80; - regvalue_b= ((8&SPI_USR_COMMAND_BITLEN)< MSBFIRST - SPI1U = SPIUMOSI; - SPI1C1 = 0; - data=pack_rgb(r,g,b); - -#endif - } - - for(y=h; y>0; y--) { - delay(0); - for(x=w; x>0; x--) { - -#ifndef SWSPI_OPTMODE - writedata(r); - writedata(g); - writedata(b); -#else - if (_hwspi) { - //noInterrupts(); -#ifdef RGB_PACK_MODE - while(SPI1CMD & SPIBUSY) {} - SPI1W0 = data; - SPI1CMD |= SPIBUSY; -#else - DIAG_PIN_CLR - WAIT_SPI_READY - DIAG_PIN_SET - - WRITE_SPI_REG(regvalue_r) - WAIT_9BITS - - DIAG_PIN_CLR - WAIT_SPI_READY - DIAG_PIN_SET - - WRITE_SPI_REG(regvalue_g) - WAIT_9BITS - - DIAG_PIN_CLR - WAIT_SPI_READY - DIAG_PIN_SET - - WRITE_SPI_REG(regvalue_b) - WAIT_9BITS - - //interrupts(); -#endif - } else { - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_cs); - - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); - - for(uint8_t bit = 0x80; bit; bit >>= 1) { - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); - if(r&bit) WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); - else WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_mosi); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); - } - - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); - - for(uint8_t bit = 0x80; bit; bit >>= 1) { - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); - if(g&bit) WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); - else WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_mosi); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); - } - - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); - - for(uint8_t bit = 0x80; bit; bit >>= 1) { - WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); - if(b&bit) WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); - else WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_mosi); - WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); - } - WRITE_PERI_REG( PIN_OUT_SET, 1<<_cs); - } - #endif - - } - - } -#ifdef RGB_PACK_MODE - // reinit old mode - while(SPI1CMD & SPIBUSY) {} - ILI9488_STOP - //spi_lcd_mode_init(); -#endif - -} -#else -// ESP32 -void ILI9488::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) { - - // rudimentary clipping (drawChar w/big text requires this) - if((x >= _width) || (y >= _height)) return; - if((x + w - 1) >= _width) w = _width - x; - if((y + h - 1) >= _height) h = _height - y; - - setAddrWindow_int(x, y, x+w-1, y+h-1); - - uint8_t r = (color & 0xF800) >> 11; - uint8_t g = (color & 0x07E0) >> 5; - uint8_t b = color & 0x001F; - - r = (r * 255) / 31; - g = (g * 255) / 63; - b = (b * 255) / 31; - -#ifdef RGB_PACK_MODE - // init 27 bit mode - uint32_t data=pack_rgb(r,g,b); - REG_SET_BIT(SPI_USER_REG(3), SPI_USR_MOSI); - REG_WRITE(SPI_MOSI_DLEN_REG(3), 27 - 1); - uint32_t *dp=(uint32_t*)SPI_W0_REG(3); - digitalWrite( _cs, LOW); -#endif - - for(y=h; y>0; y--) { - for(x=w; x>0; x--) { - #ifndef RGB_PACK_MODE - writedata(r); - writedata(g); - writedata(b); - #else - while (REG_GET_FIELD(SPI_CMD_REG(3), SPI_USR)); - *dp=data; - REG_SET_BIT(SPI_CMD_REG(3), SPI_USR); - #endif - } - } - -#ifdef RGB_PACK_MODE - while (REG_GET_FIELD(SPI_CMD_REG(3), SPI_USR)); - digitalWrite( _cs, HIGH); -#endif - - ILI9488_STOP -} -#endif - - -// Pass 8-bit (each) R,G,B, get back 16-bit packed color -uint16_t ILI9488::color565(uint8_t r, uint8_t g, uint8_t b) { - return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); -} - - -#define MADCTL_MY 0x80 -#define MADCTL_MX 0x40 -#define MADCTL_MV 0x20 -#define MADCTL_ML 0x10 -#define MADCTL_RGB 0x00 -#define MADCTL_BGR 0x08 -#define MADCTL_MH 0x04 - -void ILI9488::setRotation(uint8_t m) { - - writecommand(ILI9488_MADCTL); - rotation = m % 4; // can't be higher than 3 - switch (rotation) { - case 0: - writedata(MADCTL_MX | MADCTL_BGR); - _width = ILI9488_TFTWIDTH; - _height = ILI9488_TFTHEIGHT; - break; - case 1: - writedata(MADCTL_MV | MADCTL_BGR); - _width = ILI9488_TFTHEIGHT; - _height = ILI9488_TFTWIDTH; - break; - case 2: - writedata(MADCTL_MY | MADCTL_BGR); - _width = ILI9488_TFTWIDTH; - _height = ILI9488_TFTHEIGHT; - break; - case 3: - writedata(MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR); - _width = ILI9488_TFTHEIGHT; - _height = ILI9488_TFTWIDTH; - break; - } - ILI9488_STOP -} - - -void ILI9488::invertDisplay(boolean i) { - writecommand(i ? ILI9488_INVON : ILI9488_INVOFF); - ILI9488_STOP -} diff --git a/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/ILI9488.h b/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/ILI9488.h deleted file mode 100644 index bed25c5f8..000000000 --- a/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/ILI9488.h +++ /dev/null @@ -1,174 +0,0 @@ -/*************************************************** - STM32 Support added by Jaret Burkett at OSHlab.com - - This is our library for the Adafruit ILI9488 Breakout and Shield - ----> http://www.adafruit.com/products/1651 - - Check out the links above for our tutorials and wiring diagrams - These displays use SPI to communicate, 4 or 5 pins are required to - interface (RST is optional) - Adafruit invests time and resources providing this open source code, - please support Adafruit and open-source hardware by purchasing - products from Adafruit! - - Written by Limor Fried/Ladyada for Adafruit Industries. - MIT license, all text above must be included in any redistribution - ****************************************************/ - -#ifndef _ILI9488H_ -#define _ILI9488H_ - -#if ARDUINO >= 100 - #include "Arduino.h" - #include "Print.h" -#else - #include "WProgram.h" -#endif -#include -#ifdef __AVR - #include -#elif defined(ESP8266) - #include -#endif - -#ifdef ARDUINO_STM32_FEATHER -typedef volatile uint32 RwReg; -#endif -#if defined (__AVR__) || defined(TEENSYDUINO) || defined (__arm__) || defined (__STM32F1__) -#define USE_FAST_PINIO -#endif - -#define ILI9488_TFTWIDTH 320 -#define ILI9488_TFTHEIGHT 480 - -#define ILI9488_NOP 0x00 -#define ILI9488_SWRESET 0x01 -#define ILI9488_RDDID 0x04 -#define ILI9488_RDDST 0x09 - -#define ILI9488_SLPIN 0x10 -#define ILI9488_SLPOUT 0x11 -#define ILI9488_PTLON 0x12 -#define ILI9488_NORON 0x13 - -#define ILI9488_RDMODE 0x0A -#define ILI9488_RDMADCTL 0x0B -#define ILI9488_RDPIXFMT 0x0C -#define ILI9488_RDIMGFMT 0x0D -#define ILI9488_RDSELFDIAG 0x0F - -#define ILI9488_INVOFF 0x20 -#define ILI9488_INVON 0x21 -#define ILI9488_GAMMASET 0x26 -#define ILI9488_DISPOFF 0x28 -#define ILI9488_DISPON 0x29 - -#define ILI9488_CASET 0x2A -#define ILI9488_PASET 0x2B -#define ILI9488_RAMWR 0x2C -#define ILI9488_RAMRD 0x2E - -#define ILI9488_PTLAR 0x30 -#define ILI9488_MADCTL 0x36 -#define ILI9488_PIXFMT 0x3A - -#define ILI9488_WRCTRLD 0x53 -#define ILI9488_CAPC9 0xCF - -#define ILI9488_FRMCTR1 0xB1 -#define ILI9488_FRMCTR2 0xB2 -#define ILI9488_FRMCTR3 0xB3 -#define ILI9488_INVCTR 0xB4 -#define ILI9488_DFUNCTR 0xB6 - -#define ILI9488_PWCTR1 0xC0 -#define ILI9488_PWCTR2 0xC1 -#define ILI9488_PWCTR3 0xC2 -#define ILI9488_PWCTR4 0xC3 -#define ILI9488_PWCTR5 0xC4 -#define ILI9488_VMCTR1 0xC5 -#define ILI9488_VMCTR2 0xC7 - -#define ILI9488_RDID1 0xDA -#define ILI9488_RDID2 0xDB -#define ILI9488_RDID3 0xDC -#define ILI9488_RDID4 0xDD - -#define ILI9488_GMCTRP1 0xE0 -#define ILI9488_GMCTRN1 0xE1 -/* -#define ILI9488_PWCTR6 0xFC - -*/ - -#define PIN_OUT_SET 0x60000304 -#define PIN_OUT_CLEAR 0x60000308 - -// Color definitions -#define ILI9488_BLACK 0x0000 /* 0, 0, 0 */ -#define ILI9488_NAVY 0x000F /* 0, 0, 128 */ -#define ILI9488_DARKGREEN 0x03E0 /* 0, 128, 0 */ -#define ILI9488_DARKCYAN 0x03EF /* 0, 128, 128 */ -#define ILI9488_MAROON 0x7800 /* 128, 0, 0 */ -#define ILI9488_PURPLE 0x780F /* 128, 0, 128 */ -#define ILI9488_OLIVE 0x7BE0 /* 128, 128, 0 */ -#define ILI9488_LIGHTGREY 0xC618 /* 192, 192, 192 */ -#define ILI9488_DARKGREY 0x7BEF /* 128, 128, 128 */ -#define ILI9488_BLUE 0x001F /* 0, 0, 255 */ -#define ILI9488_GREEN 0x07E0 /* 0, 255, 0 */ -#define ILI9488_CYAN 0x07FF /* 0, 255, 255 */ -#define ILI9488_RED 0xF800 /* 255, 0, 0 */ -#define ILI9488_MAGENTA 0xF81F /* 255, 0, 255 */ -#define ILI9488_YELLOW 0xFFE0 /* 255, 255, 0 */ -#define ILI9488_WHITE 0xFFFF /* 255, 255, 255 */ -#define ILI9488_ORANGE 0xFD20 /* 255, 165, 0 */ -#define ILI9488_GREENYELLOW 0xAFE5 /* 173, 255, 47 */ -#define ILI9488_PINK 0xF81F - - - - -class ILI9488 : public Renderer { - - public: - - ILI9488(int8_t cs,int8_t mosi,int8_t sclk,int8_t bp); - - void begin(void); - void DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font); - void setAddrWindow_int(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); - void setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); - void setScrollArea(uint16_t topFixedArea, uint16_t bottomFixedArea); - void scroll(uint16_t pixels); - void pushColor(uint16_t color); - void pushColors(uint16_t *data, uint16_t len, boolean first); - //void drawImage(const uint8_t* img, uint16_t x, uint16_t y, uint16_t w, uint16_t h); - void fillScreen(uint16_t color); - void drawPixel(int16_t x, int16_t y, uint16_t color); - void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color); - void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color); - void fillRect(int16_t x, int16_t y, int16_t w, int16_t h,uint16_t color); - void setRotation(uint8_t r); - void invertDisplay(boolean i); - uint16_t color565(uint8_t r, uint8_t g, uint8_t b); - uint16_t GetColorFromIndex(uint8_t index); - void DisplayOnff(int8_t on); - void writecommand(uint8_t c); - void writedata(uint8_t d); - void write16BitColor(uint16_t color); - void commandList(uint8_t *addr); - void hw_spi_init(); - void dim(uint8_t contrast); - - private: - uint8_t tabcolor; - uint8_t dimmer; - void fastSPIwrite(uint8_t d,uint8_t dc); - void spi_lcd_mode_init(void); - void start(void); - void stop(void); - int8_t _cs, _mosi, _sclk, _bp, _hwspi; - -}; - -#endif diff --git a/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/README.md b/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/README.md deleted file mode 100644 index fd203455b..000000000 --- a/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/README.md +++ /dev/null @@ -1,8 +0,0 @@ -### ILI9488 Arduino Library -This library is for support for the 320x480 tft controller over 4 wire SPI. It is based heavily on the [Adafruit_ILI9341](https://github.com/adafruit/Adafruit_ILI9341) library and is designed to work with the [Adafruit_GFX library](https://github.com/adafruit/Adafruit-GFX-Library). - -I have made some heavy modifications, as the typical Adafruit TFT libraries are designed to work with 16bit color (RGB565), and the ILI9488 can only do 24bit (RGB888) color in 4 wire SPI mode. You can still use the library EXACTLY like you would for 16bit mode color, the colors are converted before sending to the display. What this means is, things will be slower than normal. Not only do you have to write twice as many pixels as a normal 240x320 display, 153,600px (320x480) vs 76,800px (240x320), but you also have to do a lightweight conversion on each color, and write 3 bytes vs 2bytes per pixel. - -For this reason, I do not recommend an AVR based Arduino for this library, although it will still work. I highly recommend a faster microcontroller based on ARM such as the Teensy, [STM32duino](https://github.com/rogerclarkmelbourne/Arduino_STM32), Arduino Zero, or the Arduing Due. - -On the STM32duino, DMA is supported and is therefore much faster. \ No newline at end of file diff --git a/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/examples/graphicstest/graphicstest.ino b/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/examples/graphicstest/graphicstest.ino deleted file mode 100644 index 30b0cbd9a..000000000 --- a/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/examples/graphicstest/graphicstest.ino +++ /dev/null @@ -1,350 +0,0 @@ -/*************************************************** - This is our GFX example for the Adafruit ILI9488 Breakout and Shield - ----> http://www.adafruit.com/products/1651 - - Check out the links above for our tutorials and wiring diagrams - These displays use SPI to communicate, 4 or 5 pins are required to - interface (RST is optional) - Adafruit invests time and resources providing this open source code, - please support Adafruit and open-source hardware by purchasing - products from Adafruit! - - Written by Limor Fried/Ladyada for Adafruit Industries. - MIT license, all text above must be included in any redistribution - ****************************************************/ - - -#include "SPI.h" -#include -#include - -#define TFT_CS PA1 -#define TFT_DC PB3 -#define TFT_LED PB0 -#define TFT_RST PB4 - -// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC -ILI9488 tft = ILI9488(TFT_CS, TFT_DC, TFT_RST); -// If using the breakout, change pins as desired -//Adafruit_ILI9488 tft = Adafruit_ILI9488(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO); - -void setup() { - Serial.begin(9600); - Serial.println("ILI9488 Test!"); - - tft.begin(); - - // read diagnostics (optional but can help debug problems) - uint8_t x = tft.readcommand8(ILI9488_RDMODE); - Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX); - x = tft.readcommand8(ILI9488_RDMADCTL); - Serial.print("MADCTL Mode: 0x"); Serial.println(x, HEX); - x = tft.readcommand8(ILI9488_RDPIXFMT); - Serial.print("Pixel Format: 0x"); Serial.println(x, HEX); - x = tft.readcommand8(ILI9488_RDIMGFMT); - Serial.print("Image Format: 0x"); Serial.println(x, HEX); - x = tft.readcommand8(ILI9488_RDSELFDIAG); - Serial.print("Self Diagnostic: 0x"); Serial.println(x, HEX); - - Serial.println(F("Benchmark Time (microseconds)")); - - Serial.print(F("Screen fill ")); - Serial.println(testFillScreen()); - delay(500); - - Serial.print(F("Text ")); - Serial.println(testText()); - delay(3000); - - Serial.print(F("Lines ")); - Serial.println(testLines(ILI9488_CYAN)); - delay(500); - - Serial.print(F("Horiz/Vert Lines ")); - Serial.println(testFastLines(ILI9488_RED, ILI9488_BLUE)); - delay(500); - - Serial.print(F("Rectangles (outline) ")); - Serial.println(testRects(ILI9488_GREEN)); - delay(500); - - Serial.print(F("Rectangles (filled) ")); - Serial.println(testFilledRects(ILI9488_YELLOW, ILI9488_MAGENTA)); - delay(500); - - Serial.print(F("Circles (filled) ")); - Serial.println(testFilledCircles(10, ILI9488_MAGENTA)); - - Serial.print(F("Circles (outline) ")); - Serial.println(testCircles(10, ILI9488_WHITE)); - delay(500); - - Serial.print(F("Triangles (outline) ")); - Serial.println(testTriangles()); - delay(500); - - Serial.print(F("Triangles (filled) ")); - Serial.println(testFilledTriangles()); - delay(500); - - Serial.print(F("Rounded rects (outline) ")); - Serial.println(testRoundRects()); - delay(500); - - Serial.print(F("Rounded rects (filled) ")); - Serial.println(testFilledRoundRects()); - delay(500); - - Serial.println(F("Done!")); - -} - - -void loop(void) { - for(uint8_t rotation=0; rotation<4; rotation++) { - tft.setRotation(rotation); - testText(); - delay(1000); - } -} - -unsigned long testFillScreen() { - unsigned long start = micros(); - tft.fillScreen(ILI9488_BLACK); - tft.fillScreen(ILI9488_RED); - tft.fillScreen(ILI9488_GREEN); - tft.fillScreen(ILI9488_BLUE); - tft.fillScreen(ILI9488_BLACK); - return micros() - start; -} - -unsigned long testText() { - tft.fillScreen(ILI9488_BLACK); - unsigned long start = micros(); - tft.setCursor(0, 0); - tft.setTextColor(ILI9488_WHITE); tft.setTextSize(1); - tft.println("Hello World!"); - tft.setTextColor(ILI9488_YELLOW); tft.setTextSize(2); - tft.println(1234.56); - tft.setTextColor(ILI9488_RED); tft.setTextSize(3); - tft.println(0xDEADBEEF, HEX); - tft.println(); - tft.setTextColor(ILI9488_GREEN); - tft.setTextSize(5); - tft.println("Groop"); - tft.setTextSize(2); - tft.println("I implore thee,"); - tft.setTextSize(1); - tft.println("my foonting turlingdromes."); - tft.println("And hooptiously drangle me"); - tft.println("with crinkly bindlewurdles,"); - tft.println("Or I will rend thee"); - tft.println("in the gobberwarts"); - tft.println("with my blurglecruncheon,"); - tft.println("see if I don't!"); - return micros() - start; -} - -unsigned long testLines(uint16_t color) { - unsigned long start, t; - int x1, y1, x2, y2, - w = tft.width(), - h = tft.height(); - - tft.fillScreen(ILI9488_BLACK); - - x1 = y1 = 0; - y2 = h - 1; - start = micros(); - for(x2=0; x20; i-=6) { - i2 = i / 2; - start = micros(); - tft.fillRect(cx-i2, cy-i2, i, i, color1); - t += micros() - start; - // Outlines are not included in timing results - tft.drawRect(cx-i2, cy-i2, i, i, color2); - } - - return t; -} - -unsigned long testFilledCircles(uint8_t radius, uint16_t color) { - unsigned long start; - int x, y, w = tft.width(), h = tft.height(), r2 = radius * 2; - - tft.fillScreen(ILI9488_BLACK); - start = micros(); - for(x=radius; x10; i-=5) { - start = micros(); - tft.fillTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i, - tft.color565(0, i, i)); - t += micros() - start; - tft.drawTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i, - tft.color565(i, i, 0)); - } - - return t; -} - -unsigned long testRoundRects() { - unsigned long start; - int w, i, i2, - cx = tft.width() / 2 - 1, - cy = tft.height() / 2 - 1; - - tft.fillScreen(ILI9488_BLACK); - w = min(tft.width(), tft.height()); - start = micros(); - for(i=0; i20; i-=6) { - i2 = i / 2; - tft.fillRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(0, i, 0)); - } - - return micros() - start; -} diff --git a/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/keywords.txt b/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/keywords.txt deleted file mode 100644 index 44c83b06f..000000000 --- a/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/keywords.txt +++ /dev/null @@ -1,30 +0,0 @@ -####################################### -# Syntax Coloring Map -####################################### - -####################################### -# Datatypes (KEYWORD1) -####################################### - -ILI9488 KEYWORD1 - - -####################################### -# Methods and Functions (KEYWORD2) -####################################### - -setRotation KEYWORD2 -setAddrWindow KEYWORD2 -pushColor KEYWORD2 -drawPixel KEYWORD2 -drawFastVLine KEYWORD2 -drawFastHLine KEYWORD2 -fillRect KEYWORD2 -setRotation KEYWORD2 -setRotation KEYWORD2 -height KEYWORD2 -width KEYWORD2 -invertDisplay KEYWORD2 -drawImage KEYWORD2 -setScrollArea KEYWORD2 -scroll KEYWORD2 diff --git a/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/library.properties b/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/library.properties deleted file mode 100644 index a8ae043a7..000000000 --- a/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/library.properties +++ /dev/null @@ -1,9 +0,0 @@ -name=ILI9488 -version=1.0.2 -author=Jaret Burkett -maintainer=Jaret Burkett -sentence=Library for ILI9488 displays -paragraph=Library for ILI9488 displays -category=Display -url=https://github.com/jaretburkett/ILI9488 -architectures=* diff --git a/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/spi_register.h b/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/spi_register.h deleted file mode 100644 index 340559ae1..000000000 --- a/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/spi_register.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (c) 2010 - 2011 Espressif System - * - */ - -#ifndef SPI_REGISTER_H_INCLUDED -#define SPI_REGISTER_H_INCLUDED - -#define REG_SPI_BASE(i) (0x60000200-i*0x100) -#define SPI_CMD(i) (REG_SPI_BASE(i) + 0x0) -#define SPI_USR (BIT(18)) - -#define SPI_ADDR(i) (REG_SPI_BASE(i) + 0x4) - -#define SPI_CTRL(i) (REG_SPI_BASE(i) + 0x8) -#define SPI_WR_BIT_ORDER (BIT(26)) -#define SPI_RD_BIT_ORDER (BIT(25)) -#define SPI_QIO_MODE (BIT(24)) -#define SPI_DIO_MODE (BIT(23)) -#define SPI_QOUT_MODE (BIT(20)) -#define SPI_DOUT_MODE (BIT(14)) -#define SPI_FASTRD_MODE (BIT(13)) - - - -#define SPI_RD_STATUS(i) (REG_SPI_BASE(i) + 0x10) - -#define SPI_CTRL2(i) (REG_SPI_BASE(i) + 0x14) - -#define SPI_CS_DELAY_NUM 0x0000000F -#define SPI_CS_DELAY_NUM_S 28 -#define SPI_CS_DELAY_MODE 0x00000003 -#define SPI_CS_DELAY_MODE_S 26 -#define SPI_MOSI_DELAY_NUM 0x00000007 -#define SPI_MOSI_DELAY_NUM_S 23 -#define SPI_MOSI_DELAY_MODE 0x00000003 -#define SPI_MOSI_DELAY_MODE_S 21 -#define SPI_MISO_DELAY_NUM 0x00000007 -#define SPI_MISO_DELAY_NUM_S 18 -#define SPI_MISO_DELAY_MODE 0x00000003 -#define SPI_MISO_DELAY_MODE_S 16 -#define SPI_CK_OUT_HIGH_MODE 0x0000000F -#define SPI_CK_OUT_HIGH_MODE_S 12 -#define SPI_CK_OUT_LOW_MODE 0x0000000F -#define SPI_CK_OUT_LOW_MODE_S 8 - -#define SPI_CLOCK(i) (REG_SPI_BASE(i) + 0x18) -#define SPI_CLK_EQU_SYSCLK (BIT(31)) -#define SPI_CLKDIV_PRE 0x00001FFF -#define SPI_CLKDIV_PRE_S 18 -#define SPI_CLKCNT_N 0x0000003F -#define SPI_CLKCNT_N_S 12 -#define SPI_CLKCNT_H 0x0000003F -#define SPI_CLKCNT_H_S 6 -#define SPI_CLKCNT_L 0x0000003F -#define SPI_CLKCNT_L_S 0 - -#define SPI_USER(i) (REG_SPI_BASE(i) + 0x1C) -#define SPI_USR_COMMAND (BIT(31)) -#define SPI_USR_ADDR (BIT(30)) -#define SPI_USR_DUMMY (BIT(29)) -#define SPI_USR_MISO (BIT(28)) -#define SPI_USR_MOSI (BIT(27)) - -#define SPI_USR_MOSI_HIGHPART (BIT(25)) -#define SPI_USR_MISO_HIGHPART (BIT(24)) - - -#define SPI_SIO (BIT(16)) -#define SPI_FWRITE_QIO (BIT(15)) -#define SPI_FWRITE_DIO (BIT(14)) -#define SPI_FWRITE_QUAD (BIT(13)) -#define SPI_FWRITE_DUAL (BIT(12)) -#define SPI_WR_BYTE_ORDER (BIT(11)) -#define SPI_RD_BYTE_ORDER (BIT(10)) -#define SPI_CK_OUT_EDGE (BIT(7)) -#define SPI_CK_I_EDGE (BIT(6)) -#define SPI_CS_SETUP (BIT(5)) -#define SPI_CS_HOLD (BIT(4)) -#define SPI_FLASH_MODE (BIT(2)) -#define SPI_DOUTDIN (BIT(0)) - -#define SPI_USER1(i) (REG_SPI_BASE(i) + 0x20) -#define SPI_USR_ADDR_BITLEN 0x0000003F -#define SPI_USR_ADDR_BITLEN_S 26 -#define SPI_USR_MOSI_BITLEN 0x000001FF -#define SPI_USR_MOSI_BITLEN_S 17 -#define SPI_USR_MISO_BITLEN 0x000001FF -#define SPI_USR_MISO_BITLEN_S 8 - -#define SPI_USR_DUMMY_CYCLELEN 0x000000FF -#define SPI_USR_DUMMY_CYCLELEN_S 0 - -#define SPI_USER2(i) (REG_SPI_BASE(i) + 0x24) -#define SPI_USR_COMMAND_BITLEN 0x0000000F -#define SPI_USR_COMMAND_BITLEN_S 28 -#define SPI_USR_COMMAND_VALUE 0x0000FFFF -#define SPI_USR_COMMAND_VALUE_S 0 - -#define SPI_WR_STATUS(i) (REG_SPI_BASE(i) + 0x28) -#define SPI_PIN(i) (REG_SPI_BASE(i) + 0x2C) -#define SPI_CS2_DIS (BIT(2)) -#define SPI_CS1_DIS (BIT(1)) -#define SPI_CS0_DIS (BIT(0)) -#define SPI_IDLE_EDGE (BIT(29)) - -#define SPI_SLAVE(i) (REG_SPI_BASE(i) + 0x30) -#define SPI_SYNC_RESET (BIT(31)) -#define SPI_SLAVE_MODE (BIT(30)) -#define SPI_SLV_WR_RD_BUF_EN (BIT(29)) -#define SPI_SLV_WR_RD_STA_EN (BIT(28)) -#define SPI_SLV_CMD_DEFINE (BIT(27)) -#define SPI_TRANS_CNT 0x0000000F -#define SPI_TRANS_CNT_S 23 -#define SPI_TRANS_DONE_EN (BIT(9)) -#define SPI_SLV_WR_STA_DONE_EN (BIT(8)) -#define SPI_SLV_RD_STA_DONE_EN (BIT(7)) -#define SPI_SLV_WR_BUF_DONE_EN (BIT(6)) -#define SPI_SLV_RD_BUF_DONE_EN (BIT(5)) - - - -#define SLV_SPI_INT_EN 0x0000001f -#define SLV_SPI_INT_EN_S 5 - -#define SPI_TRANS_DONE (BIT(4)) -#define SPI_SLV_WR_STA_DONE (BIT(3)) -#define SPI_SLV_RD_STA_DONE (BIT(2)) -#define SPI_SLV_WR_BUF_DONE (BIT(1)) -#define SPI_SLV_RD_BUF_DONE (BIT(0)) - -#define SPI_SLAVE1(i) (REG_SPI_BASE(i) + 0x34) -#define SPI_SLV_STATUS_BITLEN 0x0000001F -#define SPI_SLV_STATUS_BITLEN_S 27 -#define SPI_SLV_BUF_BITLEN 0x000001FF -#define SPI_SLV_BUF_BITLEN_S 16 -#define SPI_SLV_RD_ADDR_BITLEN 0x0000003F -#define SPI_SLV_RD_ADDR_BITLEN_S 10 -#define SPI_SLV_WR_ADDR_BITLEN 0x0000003F -#define SPI_SLV_WR_ADDR_BITLEN_S 4 - -#define SPI_SLV_WRSTA_DUMMY_EN (BIT(3)) -#define SPI_SLV_RDSTA_DUMMY_EN (BIT(2)) -#define SPI_SLV_WRBUF_DUMMY_EN (BIT(1)) -#define SPI_SLV_RDBUF_DUMMY_EN (BIT(0)) - - - -#define SPI_SLAVE2(i) (REG_SPI_BASE(i) + 0x38) -#define SPI_SLV_WRBUF_DUMMY_CYCLELEN 0X000000FF -#define SPI_SLV_WRBUF_DUMMY_CYCLELEN_S 24 -#define SPI_SLV_RDBUF_DUMMY_CYCLELEN 0X000000FF -#define SPI_SLV_RDBUF_DUMMY_CYCLELEN_S 16 -#define SPI_SLV_WRSTR_DUMMY_CYCLELEN 0X000000FF -#define SPI_SLV_WRSTR_DUMMY_CYCLELEN_S 8 -#define SPI_SLV_RDSTR_DUMMY_CYCLELEN 0x000000FF -#define SPI_SLV_RDSTR_DUMMY_CYCLELEN_S 0 - -#define SPI_SLAVE3(i) (REG_SPI_BASE(i) + 0x3C) -#define SPI_SLV_WRSTA_CMD_VALUE 0x000000FF -#define SPI_SLV_WRSTA_CMD_VALUE_S 24 -#define SPI_SLV_RDSTA_CMD_VALUE 0x000000FF -#define SPI_SLV_RDSTA_CMD_VALUE_S 16 -#define SPI_SLV_WRBUF_CMD_VALUE 0x000000FF -#define SPI_SLV_WRBUF_CMD_VALUE_S 8 -#define SPI_SLV_RDBUF_CMD_VALUE 0x000000FF -#define SPI_SLV_RDBUF_CMD_VALUE_S 0 - -#define SPI_W0(i) (REG_SPI_BASE(i) +0x40) -#define SPI_W1(i) (REG_SPI_BASE(i) +0x44) -#define SPI_W2(i) (REG_SPI_BASE(i) +0x48) -#define SPI_W3(i) (REG_SPI_BASE(i) +0x4C) -#define SPI_W4(i) (REG_SPI_BASE(i) +0x50) -#define SPI_W5(i) (REG_SPI_BASE(i) +0x54) -#define SPI_W6(i) (REG_SPI_BASE(i) +0x58) -#define SPI_W7(i) (REG_SPI_BASE(i) +0x5C) -#define SPI_W8(i) (REG_SPI_BASE(i) +0x60) -#define SPI_W9(i) (REG_SPI_BASE(i) +0x64) -#define SPI_W10(i) (REG_SPI_BASE(i) +0x68) -#define SPI_W11(i) (REG_SPI_BASE(i) +0x6C) -#define SPI_W12(i) (REG_SPI_BASE(i) +0x70) -#define SPI_W13(i) (REG_SPI_BASE(i) +0x74) -#define SPI_W14(i) (REG_SPI_BASE(i) +0x78) -#define SPI_W15(i) (REG_SPI_BASE(i) +0x7C) - -#define SPI_EXT3(i) (REG_SPI_BASE(i) + 0xFC) -#define SPI_INT_HOLD_ENA 0x00000003 -#define SPI_INT_HOLD_ENA_S 0 -#endif // SPI_REGISTER_H_INCLUDED diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index f8a78dc96..bf887ff19 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -704,7 +704,6 @@ #define USE_DISPLAY_ILI9341 // [DisplayModel 4] Enable ILI9341 Tft 480x320 display (+19k code) // #define USE_DISPLAY_EPAPER_29 // [DisplayModel 5] Enable e-paper 2.9 inch display (+19k code) // #define USE_DISPLAY_EPAPER_42 // [DisplayModel 6] Enable e-paper 4.2 inch display -// #define USE_DISPLAY_ILI9488 // [DisplayModel 8] [I2cDriver38] (Touch) // #define USE_DISPLAY_SSD1351 // [DisplayModel 9] Enable SSD1351 module // #define USE_DISPLAY_RA8876 // [DisplayModel 10] [I2cDriver39] (Touch) // #define USE_DISPLAY_ST7789 // [DisplayModel 12] Enable ST7789 module diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino index 6ed9eff6f..9236a511b 100644 --- a/tasmota/support_features.ino +++ b/tasmota/support_features.ino @@ -673,9 +673,9 @@ void ResponseAppendFeatures(void) #if defined(USE_SPI) && defined(USE_DISPLAY) && defined(USE_DISPLAY_EPAPER_42) feature7 |= 0x00008000; // xdsp_06_epaper_42.ino #endif -#if defined(USE_SPI) && defined(USE_DISPLAY) && defined(USE_DISPLAY_ILI9488) - feature7 |= 0x00010000; // xdsp_08_ILI9488.ino -#endif +// #if defined(USE_SPI) && defined(USE_DISPLAY) && defined(USE_DISPLAY_ILI9488) +// feature7 |= 0x00010000; // xdsp_08_ILI9488.ino +// #endif #if defined(USE_SPI) && defined(USE_DISPLAY) && defined(USE_DISPLAY_SSD1351) feature7 |= 0x00020000; // xdsp_09_SSD1351.ino #endif diff --git a/tasmota/tasmota_configurations.h b/tasmota/tasmota_configurations.h index f2fe27392..8dc302dad 100644 --- a/tasmota/tasmota_configurations.h +++ b/tasmota/tasmota_configurations.h @@ -330,7 +330,7 @@ #define USE_DISPLAY_ILI9341 // [DisplayModel 4] Enable ILI9341 Tft 480x320 display (+19k code) #define USE_DISPLAY_EPAPER_29 // [DisplayModel 5] Enable e-paper 2.9 inch display (+19k code) #define USE_DISPLAY_EPAPER_42 // [DisplayModel 6] Enable e-paper 4.2 inch display - #define USE_DISPLAY_ILI9488 // [DisplayModel 8] + // #define USE_DISPLAY_ILI9488 // [DisplayModel 8] #define USE_DISPLAY_SSD1351 // [DisplayModel 9] #define USE_DISPLAY_RA8876 // [DisplayModel 10] #define USE_DISPLAY_ST7789 // [DisplayModel 12] Enable ST7789 module diff --git a/tasmota/xdrv_13_display.ino b/tasmota/xdrv_13_display.ino index 636d0e1ce..4b4a988cf 100755 --- a/tasmota/xdrv_13_display.ino +++ b/tasmota/xdrv_13_display.ino @@ -67,7 +67,7 @@ struct MULTI_DISP { uint8_t used; } displays[MAX_MULTI_DISPLAYS]; uint8_t cur_display; -Renderer *Init_uDisplay(const char *desc, int8_t cs = -1); +Renderer *Init_uDisplay(const char *desc); void Set_display(uint8_t index) { displays[index].display = renderer; diff --git a/tasmota/xdrv_52_3_berry_display.ino b/tasmota/xdrv_52_3_berry_display.ino index cb5b47846..ed930301d 100644 --- a/tasmota/xdrv_52_3_berry_display.ino +++ b/tasmota/xdrv_52_3_berry_display.ino @@ -24,7 +24,7 @@ #include #ifdef USE_UNIVERSAL_DISPLAY -Renderer *Init_uDisplay(const char *desc, int8_t cs = -1); +Renderer *Init_uDisplay(const char *desc); #endif // USE_UNIVERSAL_DISPLAY /*********************************************************************************************\ diff --git a/tasmota/xdsp_08_ILI9488.ino b/tasmota/xdsp_08_ILI9488.ino deleted file mode 100644 index 5c3cd2f5d..000000000 --- a/tasmota/xdsp_08_ILI9488.ino +++ /dev/null @@ -1,167 +0,0 @@ -/* - xdsp_08_ILI9488.ino - Display ILI9488 support for Tasmota - - Copyright (C) 2021 Theo Arends, Gerhard Mutz - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifdef USE_SPI -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_ILI9488 - -#define XDSP_08 8 -#define XI2C_38 38 // See I2CDEVICES.md - -#define COLORED 1 -#define UNCOLORED 0 - -// using font 8 is opional (num=3) -// very badly readable, but may be useful for graphs -#define USE_TINY_FONT - - -#include -uint8_t ili9488_ctouch_counter = 0; -bool ili9488_init_done = false; - -// currently fixed -#define BACKPLANE_PIN 2 - -extern uint8_t color_type; -ILI9488 *ili9488; -extern const uint16_t picture[]; - -/*********************************************************************************************/ - -void ILI9488_InitDriver(void) { - if (PinUsed(GPIO_ILI9488_CS) && (TasmotaGlobal.spi_enabled & SPI_MOSI)) { - - Settings->display_model = XDSP_08; - - if (Settings->display_width != ILI9488_TFTWIDTH) { - Settings->display_width = ILI9488_TFTWIDTH; - } - if (Settings->display_height != ILI9488_TFTHEIGHT) { - Settings->display_height = ILI9488_TFTHEIGHT; - } - - // default colors - fg_color = ILI9488_WHITE; - bg_color = ILI9488_BLACK; - - int8_t bppin = BACKPLANE_PIN; - if (PinUsed(GPIO_BACKLIGHT)) { - bppin = Pin(GPIO_BACKLIGHT); - } - - // init renderer, must use hardware spi - ili9488 = new ILI9488(Pin(GPIO_ILI9488_CS), Pin(GPIO_SPI_MOSI), Pin(GPIO_SPI_CLK), bppin); - - ili9488->begin(); - renderer = ili9488; - renderer->DisplayInit(DISPLAY_INIT_MODE,Settings->display_size,Settings->display_rotate,Settings->display_font); - renderer->dim(GetDisplayDimmer16()); - -#ifdef SHOW_SPLASH - // Welcome text - renderer->setTextFont(2); - renderer->setTextColor(ILI9488_WHITE,ILI9488_BLACK); - renderer->DrawStringAt(50, 50, "ILI9488 TFT Display!", ILI9488_WHITE,0); - delay(1000); - - //renderer->drawRGBBitmap(100,100, picture,51,34); -#endif - - color_type = COLOR_COLOR; - // start digitizer -#ifdef USE_FT5206 - FT5206_Touch_Init(Wire); -#endif - - ili9488_init_done = true; - AddLog(LOG_LEVEL_INFO, PSTR("DSP: ILI9488")); - } -} - -#ifdef USE_FT5206 -#ifdef USE_TOUCH_BUTTONS - -void ILI9488_RotConvert(int16_t *x, int16_t *y) { -int16_t temp; - if (renderer) { - uint8_t rot=renderer->getRotation(); - switch (rot) { - case 0: - temp=*y; - *y=renderer->height()-*x; - *x=temp; - break; - case 1: - break; - case 2: - break; - case 3: - temp=*y; - *y=*x; - *x=renderer->width()-temp; - break; - } - } -} - -// check digitizer hit -void ILI9488_CheckTouch(void) { - ili9488_ctouch_counter++; - if (2 == ili9488_ctouch_counter) { - // every 100 ms should be enough - ili9488_ctouch_counter = 0; - Touch_Check(ILI9488_RotConvert); - } -} -#endif // USE_TOUCH_BUTTONS -#endif // USE_FT5206 - - -/*********************************************************************************************/ -/*********************************************************************************************\ - * Interface -\*********************************************************************************************/ -bool Xdsp08(uint8_t function) -{ - bool result = false; - - if (FUNC_DISPLAY_INIT_DRIVER == function) { - ILI9488_InitDriver(); - } - else if (ili9488_init_done && (XDSP_08 == Settings->display_model)) { - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; - case FUNC_DISPLAY_EVERY_50_MSECOND: -#ifdef USE_TOUCH_BUTTONS - if (FT5206_found) { - ILI9488_CheckTouch(); - } -#endif - break; - } - } - return result; -} - -#endif // USE_DISPLAY_ILI9488 -#endif // USE_DISPLAY -#endif // USE_SPI diff --git a/tasmota/xdsp_08_ILI9488_UD.ino b/tasmota/xdsp_08_ILI9488_UD.ino deleted file mode 100644 index 712f2fac3..000000000 --- a/tasmota/xdsp_08_ILI9488_UD.ino +++ /dev/null @@ -1,111 +0,0 @@ -/* - xdsp_08_ILI9488.ino - Display ILI9488 support for Tasmota - - Copyright (C) 2021 Theo Arends, Gerhard Mutz - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifdef USE_SPI -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_ILI9488_UD -#ifdef USE_UNIVERSAL_DISPLAY - -#define XDSP_08 8 - -bool ili9488_init_done = false; - -Renderer *Init_uDisplay(const char *desc, int8_t cs = -1); -void udisp_CheckTouch(void); - -/*********************************************************************************************/ - -const char ILI9488_DESC[] PROGMEM = -":H,ILI9488,480,320,16,SPI,1,*,*,*,*,*,*,*,10\n" -":S,2,1,1,0,40,20\n" -":I\n" -"E0,0F,00,03,09,08,16,0A,3F,78,4C,09,0A,08,16,1A,0F\n" -"E1,0F,00,16,19,03,0F,05,32,45,46,04,0E,0D,35,37,0F\n" -"C0,2,17,15\n" -"C1,1,41\n" -"C5,3,00,12,80\n" -"36,1,48\n" -"3A,1,66\n" -"B0,1,80\n" -"B1,1,A0\n" -"B4,1,02\n" -"B6,2,02,02\n" -"E9,1,00\n" -"F7,4,A9,51,2C,82\n" -"11,80\n" -"29,0\n" -":o,28\n" -":O,29\n" -":A,2A,2B,2C,16\n" -":R,36\n" -";:0,48,00,00,00\n" -":0,28,00,00,01\n" -":1,28,00,00,00\n" -":2,E8,00,00,03\n" -":3,88,00,00,02\n" -":P,18\n" -":i,20,21\n" -":TI1,38,*,*\n" -"#\n"; - -void ILI9488_InitDriver(void) { - if (PinUsed(GPIO_ILI9488_CS) && (TasmotaGlobal.spi_enabled & SPI_MOSI)) { - - renderer = Init_uDisplay(ILI9488_DESC, Pin(GPIO_ILI9488_CS)); - - if (!renderer) return; - - Settings->display_model = XDSP_08; - - ili9488_init_done = true; - } -} - -/*********************************************************************************************/ -/*********************************************************************************************\ - * Interface -\*********************************************************************************************/ -bool Xdsp08(uint8_t function) -{ - bool result = false; - - if (FUNC_DISPLAY_INIT_DRIVER == function) { - ILI9488_InitDriver(); - } - else if (ili9488_init_done && (XDSP_08 == Settings->display_model)) { - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; - case FUNC_DISPLAY_EVERY_50_MSECOND: -#ifdef USE_FT5206 - if (FT5206_found) { - udisp_CheckTouch(); - } -#endif - break; - } - } - return result; -} - -#endif // USE_UNIVERSAL_DISPLAY -#endif // USE_DISPLAY_ILI9488 -#endif // USE_DISPLAY -#endif // USE_SPI diff --git a/tasmota/xdsp_17_universal.ino b/tasmota/xdsp_17_universal.ino index 16a886661..b80205029 100644 --- a/tasmota/xdsp_17_universal.ino +++ b/tasmota/xdsp_17_universal.ino @@ -62,10 +62,11 @@ void Core2DisplayDim(uint8_t dim); const char DSP_SAMPLE_DESC[] PROGMEM = DSP_ROM_DESC #endif // DSP_ROM_DESC /*********************************************************************************************/ -Renderer *Init_uDisplay(const char *desc, int8_t cs) { +Renderer *Init_uDisplay(const char *desc) { char *ddesc = 0; char *fbuff; uDisplay *udisp; +int8_t cs; if (TasmotaGlobal.gpio_optiona.udisplay_driver || desc) { @@ -185,18 +186,16 @@ uDisplay *udisp; cp += 4; //; 7 params nr,cs,sclk,mosi,dc,bl,reset,miso //SPI,*,*,*,*,*,*,* - if (cs < 0) { - switch (*cp) { - case '1': - cs = Pin(GPIO_SPI_CS); - break; - case '2': - cs = Pin(GPIO_SPI_CS, 1); - break; - default: - cs = Pin(GPIO_SSPI_CS); - break; - } + switch (*cp) { + case '1': + cs = Pin(GPIO_SPI_CS); + break; + case '2': + cs = Pin(GPIO_SPI_CS, 1); + break; + default: + cs = Pin(GPIO_SSPI_CS); + break; } if (*cp == '1') { cp+=2; From 3f140b4b1018e0cb4e94916d3daf6eb03055cbb6 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Thu, 18 Nov 2021 20:30:16 +0100 Subject: [PATCH 060/185] Berry support for neopixel (WS2812, SK6812) --- CHANGELOG.md | 2 + .../Berry/default/be_leds_animator_lib.c | 316 +++++++++ lib/libesp32/Berry/default/be_leds_lib.c | 618 ++++++++++++++++++ .../Berry/default/be_leds_matrix_lib.c | 106 +++ lib/libesp32/Berry/default/be_leds_ntv_lib.c | 77 +++ lib/libesp32/Berry/default/be_modtab.c | 10 + lib/libesp32/Berry/default/embedded/leds.be | 141 ++++ .../Berry/default/embedded/leds_animator.be | 51 ++ tasmota/berry/leds/rainbow.be | 159 +++++ tasmota/tasmota.h | 12 + tasmota/tasmota_template.h | 2 +- tasmota/xdrv_52_3_berry_leds.ino | 299 +++++++++ tasmota/xdrv_52_9_berry.ino | 6 +- 13 files changed, 1795 insertions(+), 4 deletions(-) create mode 100644 lib/libesp32/Berry/default/be_leds_animator_lib.c create mode 100644 lib/libesp32/Berry/default/be_leds_lib.c create mode 100644 lib/libesp32/Berry/default/be_leds_matrix_lib.c create mode 100644 lib/libesp32/Berry/default/be_leds_ntv_lib.c create mode 100644 lib/libesp32/Berry/default/embedded/leds.be create mode 100644 lib/libesp32/Berry/default/embedded/leds_animator.be create mode 100644 tasmota/berry/leds/rainbow.be create mode 100644 tasmota/xdrv_52_3_berry_leds.ino diff --git a/CHANGELOG.md b/CHANGELOG.md index 98b1365fd..448585921 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ All notable changes to this project will be documented in this file. - Autoconfiguration for ESP32 and variants - ESP32 fix leftover GPIO configuration after restart - ESP32 Proof of Concept Sonoff SPM with limited functionality (switching and energy monitoring) (#13447) +- Preliminary support for Tasmota Apps (.tapp extesions) +- Berry support for neopixel (WS2812, SK6812) ### Changed - ESP8266 Gratuitous ARP enabled and set to 60 seconds (#13623) diff --git a/lib/libesp32/Berry/default/be_leds_animator_lib.c b/lib/libesp32/Berry/default/be_leds_animator_lib.c new file mode 100644 index 000000000..092d354f6 --- /dev/null +++ b/lib/libesp32/Berry/default/be_leds_animator_lib.c @@ -0,0 +1,316 @@ +/******************************************************************** + * Berry class `Leds_animator` + * + *******************************************************************/ +#include "be_constobj.h" + +#ifdef USE_WS2812 + +/******************************************************************** +** Solidified function: set_bri +********************************************************************/ +be_local_closure(set_bri, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_string("bri", 2112284244, 3), + }), + (be_nested_const_str("set_bri", -1505848517, 7)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: clear +********************************************************************/ +be_local_closure(clear, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_string("stop", -883741979, 4), + /* K1 */ be_nested_string("strip", -48555823, 5), + /* K2 */ be_nested_string("clear", 1550717474, 5), + }), + (be_nested_const_str("clear", 1550717474, 5)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 6]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x7C040200, // 0001 CALL R1 1 + 0x88040101, // 0002 GETMBR R1 R0 K1 + 0x8C040302, // 0003 GETMET R1 R1 K2 + 0x7C040200, // 0004 CALL R1 1 + 0x80000000, // 0005 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_bri +********************************************************************/ +be_local_closure(get_bri, /* name */ + be_nested_proto( + 3, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_string("bri", 2112284244, 3), + }), + (be_nested_const_str("get_bri", 2041809895, 7)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 2]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x80040400, // 0001 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: every_50ms +********************************************************************/ +be_local_closure(every_50ms, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_string("running", 343848780, 7), + /* K1 */ be_nested_string("animate", -409180496, 7), + }), + (be_nested_const_str("every_50ms", -1911083288, 10)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 5]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x78060001, // 0001 JMPF R1 #0004 + 0x8C040101, // 0002 GETMET R1 R0 K1 + 0x7C040200, // 0003 CALL R1 1 + 0x80000000, // 0004 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: stop +********************************************************************/ +be_local_closure(stop, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_string("running", 343848780, 7), + }), + (be_nested_const_str("stop", -883741979, 4)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 3]) { /* code */ + 0x50040000, // 0000 LDBOOL R1 0 0 + 0x90020001, // 0001 SETMBR R0 K0 R1 + 0x80000000, // 0002 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: remove +********************************************************************/ +be_local_closure(remove, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_string("tasmota", 424643812, 7), + /* K1 */ be_nested_string("remove_driver", 1030243768, 13), + }), + (be_nested_const_str("remove", -611183107, 6)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 5]) { /* code */ + 0xB8060000, // 0000 GETNGBL R1 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x5C0C0000, // 0002 MOVE R3 R0 + 0x7C040400, // 0003 CALL R1 2 + 0x80000000, // 0004 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: start +********************************************************************/ +be_local_closure(start, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_string("running", 343848780, 7), + }), + (be_nested_const_str("start", 1697318111, 5)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 3]) { /* code */ + 0x50040200, // 0000 LDBOOL R1 1 0 + 0x90020001, // 0001 SETMBR R0 K0 R1 + 0x80000000, // 0002 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(init, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 7]) { /* constants */ + /* K0 */ be_nested_string("strip", -48555823, 5), + /* K1 */ be_nested_string("bri", 2112284244, 3), + /* K2 */ be_nested_string("running", 343848780, 7), + /* K3 */ be_nested_string("pixel_count", -1855836553, 11), + /* K4 */ be_nested_string("clear", 1550717474, 5), + /* K5 */ be_nested_string("tasmota", 424643812, 7), + /* K6 */ be_nested_string("add_driver", 1654458371, 10), + }), + (be_nested_const_str("init", 380752755, 4)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[15]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x540A0031, // 0001 LDINT R2 50 + 0x90020202, // 0002 SETMBR R0 K1 R2 + 0x50080000, // 0003 LDBOOL R2 0 0 + 0x90020402, // 0004 SETMBR R0 K2 R2 + 0x8C080303, // 0005 GETMET R2 R1 K3 + 0x7C080200, // 0006 CALL R2 1 + 0x90020602, // 0007 SETMBR R0 K3 R2 + 0x8C080104, // 0008 GETMET R2 R0 K4 + 0x7C080200, // 0009 CALL R2 1 + 0xB80A0A00, // 000A GETNGBL R2 K5 + 0x8C080506, // 000B GETMET R2 R2 K6 + 0x5C100000, // 000C MOVE R4 R0 + 0x7C080400, // 000D CALL R2 2 + 0x80000000, // 000E RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: animate +********************************************************************/ +be_local_closure(animate, /* name */ + be_nested_proto( + 1, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + (be_nested_const_str("animate", -409180496, 7)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Leds_animator +********************************************************************/ +be_local_class(Leds_animator, + 4, + NULL, + be_nested_map(13, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_nested_key("set_bri", -1505848517, 7, 9), be_const_closure(set_bri_closure) }, + { be_nested_key("clear", 1550717474, 5, -1), be_const_closure(clear_closure) }, + { be_nested_key("running", 343848780, 7, -1), be_const_var(3) }, + { be_nested_key("get_bri", 2041809895, 7, -1), be_const_closure(get_bri_closure) }, + { be_nested_key("every_50ms", -1911083288, 10, -1), be_const_closure(every_50ms_closure) }, + { be_nested_key("bri", 2112284244, 3, 0), be_const_var(2) }, + { be_nested_key("stop", -883741979, 4, 11), be_const_closure(stop_closure) }, + { be_nested_key("remove", -611183107, 6, 1), be_const_closure(remove_closure) }, + { be_nested_key("start", 1697318111, 5, 3), be_const_closure(start_closure) }, + { be_nested_key("strip", -48555823, 5, -1), be_const_var(0) }, + { be_nested_key("pixel_count", -1855836553, 11, -1), be_const_var(1) }, + { be_nested_key("init", 380752755, 4, -1), be_const_closure(init_closure) }, + { be_nested_key("animate", -409180496, 7, 4), be_const_closure(animate_closure) }, + })), + (be_nested_const_str("Leds_animator", 142168673, 13)) +); +/*******************************************************************/ + +void be_load_Leds_animator_class(bvm *vm) { + be_pushntvclass(vm, &be_class_Leds_animator); + be_setglobal(vm, "Leds_animator"); + be_pop(vm, 1); +} + +#endif // USE_WS2812 diff --git a/lib/libesp32/Berry/default/be_leds_lib.c b/lib/libesp32/Berry/default/be_leds_lib.c new file mode 100644 index 000000000..7ddaa4b16 --- /dev/null +++ b/lib/libesp32/Berry/default/be_leds_lib.c @@ -0,0 +1,618 @@ +/******************************************************************** + * Berry class `Leds` + * + *******************************************************************/ +#include "be_constobj.h" + +#ifdef USE_WS2812 + +/******************************************************************** +** Solidified function: get_pixel_color +********************************************************************/ +be_local_closure(get_pixel_color, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_string("call_native", 1389147405, 11), + }), + (be_nested_const_str("get_pixel_color", 337490048, 15)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 5]) { /* code */ + 0x8C080100, // 0000 GETMET R2 R0 K0 + 0x5412000A, // 0001 LDINT R4 11 + 0x5C140200, // 0002 MOVE R5 R1 + 0x7C080600, // 0003 CALL R2 3 + 0x80040400, // 0004 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: pixels_buffer +********************************************************************/ +be_local_closure(pixels_buffer, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_string("call_native", 1389147405, 11), + }), + (be_nested_const_str("pixels_buffer", 1229555807, 13)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 4]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x540E0005, // 0001 LDINT R3 6 + 0x7C040400, // 0002 CALL R1 2 + 0x80040200, // 0003 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: clear +********************************************************************/ +be_local_closure(clear, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_string("clear_to", -766965166, 8), + /* K1 */ be_const_int(0), + /* K2 */ be_nested_string("show", -1454906820, 4), + }), + (be_nested_const_str("clear", 1550717474, 5)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 6]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x580C0001, // 0001 LDCONST R3 K1 + 0x7C040400, // 0002 CALL R1 2 + 0x8C040102, // 0003 GETMET R1 R0 K2 + 0x7C040200, // 0004 CALL R1 1 + 0x80000000, // 0005 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(init, /* name */ + be_nested_proto( + 9, /* nstack */ + 4, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[11]) { /* constants */ + /* K0 */ be_nested_string("gamma", -802614262, 5), + /* K1 */ be_nested_string("pin", 1866532500, 3), + /* K2 */ be_nested_string("WS2812", -755226078, 6), + /* K3 */ be_const_int(0), + /* K4 */ be_nested_string("valuer_error", -1727020191, 12), + /* K5 */ be_nested_string("no GPIO specified for neopixelbus", 42078528, 33), + /* K6 */ be_nested_string("ctor", 375399343, 4), + /* K7 */ be_nested_string("_p", 1594591802, 2), + /* K8 */ be_nested_string("internal_error", -1775809127, 14), + /* K9 */ be_nested_string("couldn't not initialize noepixelbus", -1758476484, 35), + /* K10 */ be_nested_string("begin", 1748273790, 5), + }), + (be_nested_const_str("init", 380752755, 4)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[31]) { /* code */ + 0x50100200, // 0000 LDBOOL R4 1 0 + 0x90020004, // 0001 SETMBR R0 K0 R4 + 0x4C100000, // 0002 LDNIL R4 + 0x1C100404, // 0003 EQ R4 R2 R4 + 0x78120008, // 0004 JMPF R4 #000E + 0x8C100501, // 0005 GETMET R4 R2 K1 + 0x88180502, // 0006 GETMBR R6 R2 K2 + 0x7C100400, // 0007 CALL R4 2 + 0x28100903, // 0008 GE R4 R4 K3 + 0x78120003, // 0009 JMPF R4 #000E + 0x8C100501, // 000A GETMET R4 R2 K1 + 0x88180502, // 000B GETMBR R6 R2 K2 + 0x7C100400, // 000C CALL R4 2 + 0x5C080800, // 000D MOVE R2 R4 + 0x4C100000, // 000E LDNIL R4 + 0x1C100404, // 000F EQ R4 R2 R4 + 0x78120000, // 0010 JMPF R4 #0012 + 0xB0060905, // 0011 RAISE 1 K4 K5 + 0x8C100106, // 0012 GETMET R4 R0 K6 + 0x5C180200, // 0013 MOVE R6 R1 + 0x5C1C0400, // 0014 MOVE R7 R2 + 0x5C200600, // 0015 MOVE R8 R3 + 0x7C100800, // 0016 CALL R4 4 + 0x88100107, // 0017 GETMBR R4 R0 K7 + 0x4C140000, // 0018 LDNIL R5 + 0x1C100805, // 0019 EQ R4 R4 R5 + 0x78120000, // 001A JMPF R4 #001C + 0xB0061109, // 001B RAISE 1 K8 K9 + 0x8C10010A, // 001C GETMET R4 R0 K10 + 0x7C100200, // 001D CALL R4 1 + 0x80000000, // 001E RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_pixel_color +********************************************************************/ +be_local_closure(set_pixel_color, /* name */ + be_nested_proto( + 12, /* nstack */ + 4, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_string("call_native", 1389147405, 11), + /* K1 */ be_nested_string("to_gamma", 1597139862, 8), + }), + (be_nested_const_str("set_pixel_color", 1275248356, 15)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 9]) { /* code */ + 0x8C100100, // 0000 GETMET R4 R0 K0 + 0x541A0009, // 0001 LDINT R6 10 + 0x5C1C0200, // 0002 MOVE R7 R1 + 0x8C200101, // 0003 GETMET R8 R0 K1 + 0x5C280400, // 0004 MOVE R10 R2 + 0x5C2C0600, // 0005 MOVE R11 R3 + 0x7C200600, // 0006 CALL R8 3 + 0x7C100800, // 0007 CALL R4 4 + 0x80000000, // 0008 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: begin +********************************************************************/ +be_local_closure(begin, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_string("call_native", 1389147405, 11), + /* K1 */ be_const_int(1), + }), + (be_nested_const_str("begin", 1748273790, 5)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 4]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x580C0001, // 0001 LDCONST R3 K1 + 0x7C040400, // 0002 CALL R1 2 + 0x80000000, // 0003 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: to_gamma +********************************************************************/ +be_local_closure(to_gamma, /* name */ + be_nested_proto( + 12, /* nstack */ + 3, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 7]) { /* constants */ + /* K0 */ be_nested_string("tasmota", 424643812, 7), + /* K1 */ be_nested_string("scale_uint", -1204156202, 10), + /* K2 */ be_const_int(0), + /* K3 */ be_const_int(16711680), + /* K4 */ be_nested_string("gamma", -802614262, 5), + /* K5 */ be_nested_string("light", -493019601, 5), + /* K6 */ be_nested_string("gamma8", -492123466, 6), + }), + (be_nested_const_str("to_gamma", 1597139862, 8)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[67]) { /* code */ + 0x4C0C0000, // 0000 LDNIL R3 + 0x200C0403, // 0001 NE R3 R2 R3 + 0x780E0001, // 0002 JMPF R3 #0005 + 0x5C0C0400, // 0003 MOVE R3 R2 + 0x70020000, // 0004 JMP #0006 + 0x540E0063, // 0005 LDINT R3 100 + 0x5C080600, // 0006 MOVE R2 R3 + 0xB80E0000, // 0007 GETNGBL R3 K0 + 0x8C0C0701, // 0008 GETMET R3 R3 K1 + 0x5C140400, // 0009 MOVE R5 R2 + 0x58180002, // 000A LDCONST R6 K2 + 0x541E0063, // 000B LDINT R7 100 + 0x58200002, // 000C LDCONST R8 K2 + 0x2C240303, // 000D AND R9 R1 K3 + 0x542A000F, // 000E LDINT R10 16 + 0x3C24120A, // 000F SHR R9 R9 R10 + 0x7C0C0C00, // 0010 CALL R3 6 + 0xB8120000, // 0011 GETNGBL R4 K0 + 0x8C100901, // 0012 GETMET R4 R4 K1 + 0x5C180400, // 0013 MOVE R6 R2 + 0x581C0002, // 0014 LDCONST R7 K2 + 0x54220063, // 0015 LDINT R8 100 + 0x58240002, // 0016 LDCONST R9 K2 + 0x542AFEFF, // 0017 LDINT R10 65280 + 0x2C28020A, // 0018 AND R10 R1 R10 + 0x542E0007, // 0019 LDINT R11 8 + 0x3C28140B, // 001A SHR R10 R10 R11 + 0x7C100C00, // 001B CALL R4 6 + 0xB8160000, // 001C GETNGBL R5 K0 + 0x8C140B01, // 001D GETMET R5 R5 K1 + 0x5C1C0400, // 001E MOVE R7 R2 + 0x58200002, // 001F LDCONST R8 K2 + 0x54260063, // 0020 LDINT R9 100 + 0x58280002, // 0021 LDCONST R10 K2 + 0x542E00FE, // 0022 LDINT R11 255 + 0x2C2C020B, // 0023 AND R11 R1 R11 + 0x7C140C00, // 0024 CALL R5 6 + 0x88180104, // 0025 GETMBR R6 R0 K4 + 0x781A0013, // 0026 JMPF R6 #003B + 0xB81A0A00, // 0027 GETNGBL R6 K5 + 0x8C180D06, // 0028 GETMET R6 R6 K6 + 0x5C200600, // 0029 MOVE R8 R3 + 0x7C180400, // 002A CALL R6 2 + 0x541E000F, // 002B LDINT R7 16 + 0x38180C07, // 002C SHL R6 R6 R7 + 0xB81E0A00, // 002D GETNGBL R7 K5 + 0x8C1C0F06, // 002E GETMET R7 R7 K6 + 0x5C240800, // 002F MOVE R9 R4 + 0x7C1C0400, // 0030 CALL R7 2 + 0x54220007, // 0031 LDINT R8 8 + 0x381C0E08, // 0032 SHL R7 R7 R8 + 0x30180C07, // 0033 OR R6 R6 R7 + 0xB81E0A00, // 0034 GETNGBL R7 K5 + 0x8C1C0F06, // 0035 GETMET R7 R7 K6 + 0x5C240A00, // 0036 MOVE R9 R5 + 0x7C1C0400, // 0037 CALL R7 2 + 0x30180C07, // 0038 OR R6 R6 R7 + 0x80040C00, // 0039 RET 1 R6 + 0x70020006, // 003A JMP #0042 + 0x541A000F, // 003B LDINT R6 16 + 0x38180606, // 003C SHL R6 R3 R6 + 0x541E0007, // 003D LDINT R7 8 + 0x381C0807, // 003E SHL R7 R4 R7 + 0x30180C07, // 003F OR R6 R6 R7 + 0x30180C05, // 0040 OR R6 R6 R5 + 0x80040C00, // 0041 RET 1 R6 + 0x80000000, // 0042 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: pixel_count +********************************************************************/ +be_local_closure(pixel_count, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_string("call_native", 1389147405, 11), + }), + (be_nested_const_str("pixel_count", -1855836553, 11)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 4]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x540E0007, // 0001 LDINT R3 8 + 0x7C040400, // 0002 CALL R1 2 + 0x80040200, // 0003 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: can_show +********************************************************************/ +be_local_closure(can_show, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_string("call_native", 1389147405, 11), + /* K1 */ be_const_int(3), + }), + (be_nested_const_str("can_show", 960091187, 8)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 4]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x580C0001, // 0001 LDCONST R3 K1 + 0x7C040400, // 0002 CALL R1 2 + 0x80040200, // 0003 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: pixel_size +********************************************************************/ +be_local_closure(pixel_size, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_string("call_native", 1389147405, 11), + }), + (be_nested_const_str("pixel_size", -2085831511, 10)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 4]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x540E0006, // 0001 LDINT R3 7 + 0x7C040400, // 0002 CALL R1 2 + 0x80040200, // 0003 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: dirty +********************************************************************/ +be_local_closure(dirty, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_string("call_native", 1389147405, 11), + }), + (be_nested_const_str("dirty", -1627386213, 5)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 4]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x540E0004, // 0001 LDINT R3 5 + 0x7C040400, // 0002 CALL R1 2 + 0x80000000, // 0003 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: show +********************************************************************/ +be_local_closure(show, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_string("call_native", 1389147405, 11), + /* K1 */ be_const_int(2), + }), + (be_nested_const_str("show", -1454906820, 4)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 4]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x580C0001, // 0001 LDCONST R3 K1 + 0x7C040400, // 0002 CALL R1 2 + 0x80000000, // 0003 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: clear_to +********************************************************************/ +be_local_closure(clear_to, /* name */ + be_nested_proto( + 10, /* nstack */ + 3, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_string("call_native", 1389147405, 11), + /* K1 */ be_nested_string("to_gamma", 1597139862, 8), + }), + (be_nested_const_str("clear_to", -766965166, 8)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 8]) { /* code */ + 0x8C0C0100, // 0000 GETMET R3 R0 K0 + 0x54160008, // 0001 LDINT R5 9 + 0x8C180101, // 0002 GETMET R6 R0 K1 + 0x5C200200, // 0003 MOVE R8 R1 + 0x5C240400, // 0004 MOVE R9 R2 + 0x7C180600, // 0005 CALL R6 3 + 0x7C0C0600, // 0006 CALL R3 3 + 0x80000000, // 0007 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: is_dirty +********************************************************************/ +be_local_closure(is_dirty, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_string("call_native", 1389147405, 11), + }), + (be_nested_const_str("is_dirty", 418034110, 8)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 4]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x540E0003, // 0001 LDINT R3 4 + 0x7C040400, // 0002 CALL R1 2 + 0x80040200, // 0003 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: ctor +********************************************************************/ +be_local_closure(ctor, /* name */ + be_nested_proto( + 10, /* nstack */ + 4, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_string("call_native", 1389147405, 11), + /* K1 */ be_const_int(0), + }), + (be_nested_const_str("ctor", 375399343, 4)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[16]) { /* code */ + 0x4C100000, // 0000 LDNIL R4 + 0x1C100604, // 0001 EQ R4 R3 R4 + 0x78120005, // 0002 JMPF R4 #0009 + 0x8C100100, // 0003 GETMET R4 R0 K0 + 0x58180001, // 0004 LDCONST R6 K1 + 0x5C1C0200, // 0005 MOVE R7 R1 + 0x5C200400, // 0006 MOVE R8 R2 + 0x7C100800, // 0007 CALL R4 4 + 0x70020005, // 0008 JMP #000F + 0x8C100100, // 0009 GETMET R4 R0 K0 + 0x58180001, // 000A LDCONST R6 K1 + 0x5C1C0200, // 000B MOVE R7 R1 + 0x5C200400, // 000C MOVE R8 R2 + 0x5C240600, // 000D MOVE R9 R3 + 0x7C100A00, // 000E CALL R4 5 + 0x80000000, // 000F RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Leds +********************************************************************/ +extern const bclass be_class_Leds_ntv; +be_local_class(Leds, + 1, + &be_class_Leds_ntv, + be_nested_map(16, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_nested_key("get_pixel_color", 337490048, 15, -1), be_const_closure(get_pixel_color_closure) }, + { be_nested_key("pixels_buffer", 1229555807, 13, -1), be_const_closure(pixels_buffer_closure) }, + { be_nested_key("clear", 1550717474, 5, 13), be_const_closure(clear_closure) }, + { be_nested_key("init", 380752755, 4, 8), be_const_closure(init_closure) }, + { be_nested_key("set_pixel_color", 1275248356, 15, -1), be_const_closure(set_pixel_color_closure) }, + { be_nested_key("begin", 1748273790, 5, -1), be_const_closure(begin_closure) }, + { be_nested_key("to_gamma", 1597139862, 8, -1), be_const_closure(to_gamma_closure) }, + { be_nested_key("pixel_count", -1855836553, 11, -1), be_const_closure(pixel_count_closure) }, + { be_nested_key("can_show", 960091187, 8, -1), be_const_closure(can_show_closure) }, + { be_nested_key("pixel_size", -2085831511, 10, -1), be_const_closure(pixel_size_closure) }, + { be_nested_key("gamma", -802614262, 5, -1), be_const_var(0) }, + { be_nested_key("dirty", -1627386213, 5, -1), be_const_closure(dirty_closure) }, + { be_nested_key("show", -1454906820, 4, -1), be_const_closure(show_closure) }, + { be_nested_key("clear_to", -766965166, 8, -1), be_const_closure(clear_to_closure) }, + { be_nested_key("is_dirty", 418034110, 8, 5), be_const_closure(is_dirty_closure) }, + { be_nested_key("ctor", 375399343, 4, 1), be_const_closure(ctor_closure) }, + })), + (be_nested_const_str("Leds", -1585722021, 4)) +); +/*******************************************************************/ + +void be_load_Leds_class(bvm *vm) { + be_pushntvclass(vm, &be_class_Leds); + be_setglobal(vm, "Leds"); + be_pop(vm, 1); +} + +#endif // USE_WS2812 diff --git a/lib/libesp32/Berry/default/be_leds_matrix_lib.c b/lib/libesp32/Berry/default/be_leds_matrix_lib.c new file mode 100644 index 000000000..b6d83bb18 --- /dev/null +++ b/lib/libesp32/Berry/default/be_leds_matrix_lib.c @@ -0,0 +1,106 @@ +/******************************************************************** + * Berry class `Leds_matrix` + * + *******************************************************************/ +#include "be_constobj.h" + +#ifdef USE_WS2812 + +/******************************************************************** +** Solidified function: set_matrix_pixel_color +********************************************************************/ +be_local_closure(set_matrix_pixel_color, /* name */ + be_nested_proto( + 10, /* nstack */ + 5, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_string("set_pixel_color", 1275248356, 15), + /* K1 */ be_nested_string("w", -234078410, 1), + }), + (be_nested_const_str("set_matrix_pixel_color", 1197149462, 22)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 8]) { /* code */ + 0x8C140100, // 0000 GETMET R5 R0 K0 + 0x881C0101, // 0001 GETMBR R7 R0 K1 + 0x081C0207, // 0002 MUL R7 R1 R7 + 0x001C0E02, // 0003 ADD R7 R7 R2 + 0x5C200600, // 0004 MOVE R8 R3 + 0x5C240800, // 0005 MOVE R9 R4 + 0x7C140800, // 0006 CALL R5 4 + 0x80000000, // 0007 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(init, /* name */ + be_nested_proto( + 10, /* nstack */ + 5, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_string("w", -234078410, 1), + /* K1 */ be_nested_string("h", -317966505, 1), + /* K2 */ be_nested_string("init", 380752755, 4), + }), + (be_nested_const_str("init", 380752755, 4)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[11]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x90020202, // 0001 SETMBR R0 K1 R2 + 0x60140003, // 0002 GETGBL R5 G3 + 0x5C180000, // 0003 MOVE R6 R0 + 0x7C140200, // 0004 CALL R5 1 + 0x8C140B02, // 0005 GETMET R5 R5 K2 + 0x081C0202, // 0006 MUL R7 R1 R2 + 0x5C200600, // 0007 MOVE R8 R3 + 0x5C240800, // 0008 MOVE R9 R4 + 0x7C140800, // 0009 CALL R5 4 + 0x80000000, // 000A RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Leds_matrix +********************************************************************/ +extern const bclass be_class_Leds; +be_local_class(Leds_matrix, + 2, + &be_class_Leds, + be_nested_map(4, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_nested_key("h", -317966505, 1, -1), be_const_var(0) }, + { be_nested_key("w", -234078410, 1, -1), be_const_var(1) }, + { be_nested_key("set_matrix_pixel_color", 1197149462, 22, 1), be_const_closure(set_matrix_pixel_color_closure) }, + { be_nested_key("init", 380752755, 4, 0), be_const_closure(init_closure) }, + })), + (be_nested_const_str("Leds_matrix", -1450073227, 11)) +); +/*******************************************************************/ + +void be_load_Leds_matrix_class(bvm *vm) { + be_pushntvclass(vm, &be_class_Leds_matrix); + be_setglobal(vm, "Leds_matrix"); + be_pop(vm, 1); +} + + +#endif // USE_WS2812 diff --git a/lib/libesp32/Berry/default/be_leds_ntv_lib.c b/lib/libesp32/Berry/default/be_leds_ntv_lib.c new file mode 100644 index 000000000..8d09f952b --- /dev/null +++ b/lib/libesp32/Berry/default/be_leds_ntv_lib.c @@ -0,0 +1,77 @@ +/******************************************************************** + * Berry class `neopixelbus_ntv` + * + *******************************************************************/ +/* + +class Leds_ntv + var _p # pointer to internal object of type `NeoPixelBus(uint16_t countPixels, uint8_t pin)` + var _t # type of led strip + static WS2812_GRB = 1 + static WS2812_GRBW = 2 + static SK6812_GRB = 3 + static SK6812_GRBW = 4 + + # skeleton for native call + def call_native() end +end + +*/ +#include "be_constobj.h" + +#ifdef USE_WS2812 + +extern int be_neopixelbus_call_native(bvm *vm); + +/******************************************************************** +** Solidified function: call_native +********************************************************************/ +be_local_closure(call_native, /* name */ + be_nested_proto( + 1, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + (be_nested_const_str("call_native", 1389147405, 11)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Leds_ntv +********************************************************************/ +be_local_class(Leds_ntv, + 2, + NULL, + be_nested_map(7, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_nested_key("WS2812_GRB", 1736405692, 10, 3), be_const_int(1) }, + { be_nested_key("WS2812_GRBW", -660477967, 11, -1), be_const_int(2) }, + { be_nested_key("call_native", 1389147405, 11, 1), be_const_func(be_neopixelbus_call_native) }, + { be_nested_key("_t", 1527481326, 2, -1), be_const_var(1) }, + { be_nested_key("SK6812_GRBW", 81157857, 11, -1), be_const_int(4) }, + { be_nested_key("SK6812_GRB", 1159411308, 10, -1), be_const_int(3) }, + { be_nested_key("_p", 1594591802, 2, 5), be_const_var(0) }, + })), + (be_nested_const_str("Leds_ntv", -292677248, 8)) +); +/*******************************************************************/ + +void be_load_Leds_ntv_class(bvm *vm) { + be_pushntvclass(vm, &be_class_Leds_ntv); + be_setglobal(vm, "Leds_ntv"); + be_pop(vm, 1); +} + +// be_const_func(be_neopixelbus_call_native) +#endif // USE_WS2812 diff --git a/lib/libesp32/Berry/default/be_modtab.c b/lib/libesp32/Berry/default/be_modtab.c index 7e1a1bad9..df2b93843 100644 --- a/lib/libesp32/Berry/default/be_modtab.c +++ b/lib/libesp32/Berry/default/be_modtab.c @@ -132,6 +132,10 @@ extern void be_load_AXP192_class(bvm *vm); extern void be_load_md5_lib(bvm *vm); extern void be_load_webclient_lib(bvm *vm); extern void be_load_crypto_lib(bvm *vm); +extern void be_load_Leds_ntv_class(bvm *vm); +extern void be_load_Leds_class(bvm *vm); +extern void be_load_Leds_matrix_class(bvm *vm); +extern void be_load_Leds_animator_class(bvm *vm); extern void be_load_ctypes_lib(bvm *vm); extern void be_load_ctypes_energy_definitions_lib(bvm *vm); @@ -186,6 +190,12 @@ BERRY_API void be_load_custom_libs(bvm *vm) #if defined(USE_ONEWIRE) || defined(USE_DS18x20) be_load_onewirelib(vm); #endif +#ifdef USE_WS2812 + be_load_Leds_ntv_class(vm); + be_load_Leds_class(vm); + be_load_Leds_matrix_class(vm); + be_load_Leds_animator_class(vm); +#endif // USE_WS2812 #ifdef USE_I2S_AUDIO_BERRY be_load_driver_audio_lib(vm); #endif diff --git a/lib/libesp32/Berry/default/embedded/leds.be b/lib/libesp32/Berry/default/embedded/leds.be new file mode 100644 index 000000000..aed675125 --- /dev/null +++ b/lib/libesp32/Berry/default/embedded/leds.be @@ -0,0 +1,141 @@ +# class Leds +# +# for adressable leds like NoePixel + + +# Native commands +# 00 : ctor (leds:int, gpio:int) -> void +# 01 : begin void -> void +# 02 : show void -> void +# 03 : CanShow void -> bool +# 04 : IsDirty void -> bool +# 05 : Dirty void -> void +# 06 : Pixels void -> bytes() (mapped to the buffer) +# 07 : PixelSize void -> int +# 08 : PixelCount void -> int +# 09 : ClearTo (color:??) -> void +# 10 : SetPixelColor (idx:int, color:??) -> void +# 11 : GetPixelColor (idx:int) -> color:?? +# 20 : RotateLeft (rot:int [, first:int, last:int]) -> void +# 21 : RotateRight (rot:int [, first:int, last:int]) -> void +# 22 : ShiftLeft (rot:int [, first:int, last:int]) -> void +# 23 : ShiftRight (rot:int [, first:int, last:int]) -> void + + +class Leds : Leds_ntv + var gamma # if true, apply gamma (true is default) + # leds:int = number of leds of the strip + # gpio:int (optional) = GPIO for NeoPixel. If not specified, takes the WS2812 gpio + # type:int (optional) = Type of LED, defaults to WS2812 RGB + # rmt:int (optional) = RMT hardware channel to use, leave default unless you have a good reason + def init(leds, gpio, type, rmt) # rmt is optional + self.gamma = true # gamma is enabled by default, it should be disabled explicitly if needed + + if gpio == nil && gpio.pin(gpio.WS2812) >= 0 + gpio = gpio.pin(gpio.WS2812) + end + + # if no GPIO, abort + if gpio == nil + raise "valuer_error", "no GPIO specified for neopixelbus" + end + + # initialize the structure + self.ctor(leds, gpio, type, rmt) + + if self._p == nil raise "internal_error", "couldn't not initialize noepixelbus" end + + # call begin + self.begin() + + end + + def clear() + self.clear_to(0x000000) + self.show() + end + + def ctor(leds, gpio, rmt) + if rmt == nil + self.call_native(0, leds, gpio) + else + self.call_native(0, leds, gpio, rmt) + end + end + def begin() + self.call_native(1) + end + def show() + self.call_native(2) + end + def can_show() + return self.call_native(3) + end + def is_dirty() + return self.call_native(4) + end + def dirty() + self.call_native(5) + end + def pixels_buffer() + return self.call_native(6) + end + def pixel_size() + return self.call_native(7) + end + def pixel_count() + return self.call_native(8) + end + def clear_to(col, bri) + self.call_native(9, self.to_gamma(col, bri)) + end + def set_pixel_color(idx, col, bri) + self.call_native(10, idx, self.to_gamma(col, bri)) + end + def get_pixel_color(idx) + return self.call_native(11, idx) + end + # def rotate_left(rot, first, last) + # self.call_native(20, rot, first, last) + # end + # def rotate_right(rot, first, last) + # self.call_native(21, rot, first, last) + # end + # def shift_left(rot, first, last) + # self.call_native(22, rot, first, last) + # end + # def shift_right(rot, first, last) + # self.call_native(22, rot, first, last) + # end + + # apply gamma and bri + def to_gamma(rgbw, bri) + bri = (bri != nil) ? bri : 100 + var r = tasmota.scale_uint(bri, 0, 100, 0, (rgbw & 0xFF0000) >> 16) + var g = tasmota.scale_uint(bri, 0, 100, 0, (rgbw & 0x00FF00) >> 8) + var b = tasmota.scale_uint(bri, 0, 100, 0, (rgbw & 0x0000FF)) + if self.gamma + return light.gamma8(r) << 16 | + light.gamma8(g) << 8 | + light.gamma8(b) + else + return r << 16 | + g << 8 | + b + end + end +end + +class Leds_matrix : Leds + var h, w + + def init(w, h, gpio, rmt) + self.w = w + self.h = h + super(self).init(w * h, gpio, rmt) + end + + def set_matrix_pixel_color(x, y, col, bri) + self.set_pixel_color(x * self.w + y, col, bri) + end +end diff --git a/lib/libesp32/Berry/default/embedded/leds_animator.be b/lib/libesp32/Berry/default/embedded/leds_animator.be new file mode 100644 index 000000000..c57fd87bf --- /dev/null +++ b/lib/libesp32/Berry/default/embedded/leds_animator.be @@ -0,0 +1,51 @@ +# class Leds_animator + +class Leds_animator + var strip # neopixelbus object + var pixel_count # number of pixels in the strip + var bri # brightness of the animation, 0..100, default 50 + var running # is the animation running + + def init(strip) + self.strip = strip + self.bri = 50 # percentage of brightness 0..100 + self.running = false + self.pixel_count = strip.pixel_count() + # + self.clear() # clear all leds first + # + tasmota.add_driver(self) + end + + def clear() + self.stop() + self.strip.clear() + end + def start() + self.running = true + end + def stop() + self.running = false + end + + def set_bri(bri) + self.bri = bri + end + def get_bri(bri) + return self.bri + end + + def every_50ms() + if self.running + self.animate() + end + end + + def animate() + # placeholder - do nothing by default + end + + def remove() + tasmota.remove_driver(self) + end +end diff --git a/tasmota/berry/leds/rainbow.be b/tasmota/berry/leds/rainbow.be new file mode 100644 index 000000000..eebd485a3 --- /dev/null +++ b/tasmota/berry/leds/rainbow.be @@ -0,0 +1,159 @@ +# simple Rainbow animator + +#- +# Ex: if WS2812 configured to WS2812 - channel 2 + +var strip = neopixelbus(25, gpio.pin(gpio.WS2812, 1)) +rainbow = Rainbow(strip) +rainbow.start() + +-# + +# https://stackoverflow.com/questions/34187171/fast-integer-square-root-approximation +def fast_sqrt_int(val) + var a, b + + if val < 2 return val end + + a = 1255 # starting point is relatively unimportant + + b = val / a; a = (a+b) /2; + b = val / a; a = (a+b) /2; + b = val / a; a = (a+b) /2; + b = val / a; a = (a+b) /2; + b = val / a; a = (a+b) /2; + b = val / a; a = (a+b) /2; + if (val < 20000) + b = val / a; a = (a+b) /2; + b = val / a; a = (a+b) /2; + end + + return a +end + +class Rainbow : Leds_animator + var cur_offset # current offset in the palette + static palette = [ 0xFF0000, #- red -# + 0xFFA500, #- orange -# + 0xFFFF00, #- yellow -# + 0x008800, #- green -# + 0x0000FF, #- blue -# + 0x4B0082, #- indigo -# + 0xEE82EE, #- violet -# + ] + + def init(strip) + super(self).init(strip) + self.cur_offset = 0 + end + + def animate() + var i = 0 + # move instance variables to registers to avoid GETMBR inside the loop + var cur_offset = self.cur_offset + var modulus = size(self.palette) + var palette = self.palette + var strip = self.strip + var bri = self.bri + var set_pixel_color = strip.set_pixel_color + + while i < self.pixel_count # doing a loop rather than a `for` prevents from allocating a new object + var col = palette[(cur_offset + i) % modulus] + set_pixel_color(strip, i, col, bri) # simulate the method call without GETMET + i += 1 + end + strip.show() + # advance to next color + self.cur_offset = (self.cur_offset + 1) % modulus + end + +end + +class Rainbow_Matrix : Leds_animator + var cur_offset # current offset in the palette + static palette = [ 0xFF0000, #- red -# + 0xFFA500, #- orange -# + 0xFFFF00, #- yellow -# + 0x008800, #- green -# + 0x0000FF, #- blue -# + 0x4B0082, #- indigo -# + 0xEE82EE, #- violet -# + ] + + def init(strip) + super(self).init(strip) + self.cur_offset = 0 + end + + def animate() + # move instance variables to registers to avoid GETMBR inside the loop + var cur_offset = self.cur_offset + var modulus = size(self.palette) + var palette = self.palette + var strip = self.strip + var bri = self.bri + var set_matrix_pixel_color = strip.set_matrix_pixel_color + var h = self.strip.h + var w = self.strip.w + + var y = 0 + while y < h + var x = 0 + while x < w + var col = palette[(cur_offset + y) % modulus] + set_matrix_pixel_color(strip, x, y, col, bri) # simulate the method call without GETMET + x += 1 + end + y += 1 + end + strip.show() + # advance to next color + self.cur_offset = (self.cur_offset + 1) % modulus + end + +end + + +class Round : Leds_animator + var cur_val + var min_val, max_val + var incr_val + + def init(strip) + super(self).init(strip) + self.cur_val = 5 << 8 + self.min_val = 2 << 8 + self.max_val = 6 << 8 + self.incr_val = 50 + end + + def animate() + # move instance variables to registers to avoid GETMBR inside the loop + var strip = self.strip + var bri = self.bri + var set_matrix_pixel_color = strip.set_matrix_pixel_color + var h = self.strip.h + var w = self.strip.w + var ch = h / 2 + var cw = w / 2 + + var y = 0 + while y < h + var x = 0 + while x < w + var col = 0xFF0000 # red + var dist = fast_sqrt_int( ((y - ch)*(y - ch) + (x - cw)*(x - cw)) << 16) + var rel_bri = tasmota.scale_uint(dist, 0, self.cur_val, bri, 0) + set_matrix_pixel_color(strip, x, y, col, rel_bri) # simulate the method call without GETMET + x += 1 + end + y += 1 + end + strip.show() + # + self.cur_val += self.incr_val + if self.cur_val > self.max_val self.cur_val = self.max_val self.incr_val = -self.incr_val end + if self.cur_val < self.min_val self.cur_val = self.min_val self.incr_val = -self.incr_val end + end + +end diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index 92803ca87..f6a2b113d 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -83,10 +83,22 @@ const uint16_t VL53L0X_MAX_SENSORS = 8; // Max number of VL53L0X sensors const uint8_t MAX_I2C = 2; // Max number of I2C controllers (ESP32 = 2) const uint8_t MAX_SPI = 2; // Max number of Hardware SPI controllers (ESP32 = 2) const uint8_t MAX_I2S = 2; // Max number of Hardware I2S controllers (ESP32 = 2) + +#if CONFIG_IDF_TARGET_ESP32 +const uint8_t MAX_RMT = 8; // Max number or RMT channels (ESP32 only) +#elif CONFIG_IDF_TARGET_ESP32S2 +const uint8_t MAX_RMT = 4; // Max number or RMT channels (ESP32S2 only) +#elif CONFIG_IDF_TARGET_ESP32C3 +const uint8_t MAX_RMT = 2; // Max number or RMT channels (ESP32C3 only) +#else +const uint8_t MAX_RMT = 0; // Max number or RMT channels (0 if unknown) +#endif + #else const uint8_t MAX_I2C = 0; // Max number of I2C controllers (ESP8266 = 0, no choice) const uint8_t MAX_SPI = 0; // Max number of Hardware SPI controllers (ESP8266 = 0, no choice) const uint8_t MAX_I2S = 0; // Max number of Hardware I2S controllers (ESP8266 = 0, no choice) +const uint8_t MAX_RMT = 0; // No RMT channel on ESP8266 #endif // Changes to the following MAX_ defines need to be in line with enum SettingsTextIndex diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index 4f9b41b4b..bbbce4d01 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -569,7 +569,7 @@ const uint16_t kGpioNiceList[] PROGMEM = { AGPIO(GPIO_P9813_CLK), // P9813 CLOCK AGPIO(GPIO_P9813_DAT), // P9813 DATA #else - AGPIO(GPIO_WS2812), // WS2812 Led string + AGPIO(GPIO_WS2812) + MAX_RMT,// WS2812 Led string, using RMT on ESP32 #endif // NEO_HW_P9813 #endif #ifdef USE_ARILUX_RF diff --git a/tasmota/xdrv_52_3_berry_leds.ino b/tasmota/xdrv_52_3_berry_leds.ino new file mode 100644 index 000000000..5e7d95b77 --- /dev/null +++ b/tasmota/xdrv_52_3_berry_leds.ino @@ -0,0 +1,299 @@ +/* + xdrv_52_3_berry_leds.ino - Berry scripting language, native fucnctions + + Copyright (C) 2021 Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + +#ifdef USE_BERRY + +#include + +#ifdef USE_WS2812 + +#include + +enum { + ws2812_grb = 1, + ws2812_grbw = 2, + sk6812_grb = 3, + sk6812_grbw = 4, + + neopixel_type_end +}; + +typedef NeoPixelBus neopixel_ws2812_grb_t; +typedef NeoPixelBus neopixel_ws2812_grbw_t; +typedef NeoPixelBus neopixel_sk6812_grb_t; +typedef NeoPixelBus neopixel_sk6812_grbw_t; + + +/*********************************************************************************************\ + * Native functions mapped to Berry functions + * + * import unishox + * + * +\*********************************************************************************************/ +extern "C" { + + // # Native commands + // # 00 : ctor + // # 01 : begin void -> void + // # 02 : show void -> void + // # 03 : CanShow void -> bool + // # 04 : IsDirty void -> bool + // # 05 : Dirty void -> void + // # 06 : Pixels void -> bytes() (mapped to the buffer) + // # 07 : PixelSize void -> int + // # 08 : PixelCount void -> int + // # 09 : ClearTo (color:??) -> void + // # 10 : SetPixelColor (idx:int, color:??) -> void + // # 11 : GetPixelColor (idx:int) -> color:?? + // # 20 : RotateLeft (rot:int [, first:int, last:int]) -> void + // # 21 : RotateRight (rot:int [, first:int, last:int]) -> void + // # 22 : ShiftLeft (rot:int [, first:int, last:int]) -> void + // # 23 : ShiftRight (rot:int [, first:int, last:int]) -> void + + void * be_get_neopixelbus(bvm *vm) { + be_getmember(vm, 1, "_p"); + void * strip = (void*) be_tocomptr(vm, -1); + be_pop(vm, 1); + if (strip == nullptr) { + be_raise(vm, "internal_error", "neopixelbus object not initialized"); + } + return strip; + } + int32_t be_get_leds_type(bvm *vm) { + be_getmember(vm, 1, "_t"); + int32_t type = be_toint(vm, -1); + be_pop(vm, 1); + if (type <= 0 || type >= neopixel_type_end) { + be_raise(vm, "internal_error", "invalid leds type"); + } + return type; + } + + int be_neopixelbus_call_native(bvm *vm); + int be_neopixelbus_call_native(bvm *vm) { + int32_t argc = be_top(vm); // Get the number of arguments + if (argc >= 2 && be_isint(vm, 2)) { + int32_t cmd = be_toint(vm, 2); + + if (0 == cmd) { // 00 : ctor (leds:int, gpio:int) -> void + if (!(argc >= 4 && be_isint(vm, 3) && be_isint(vm, 4))) { + be_raise(vm, "value_error", "bad arguments for neopixelbus:ctor"); + } + int32_t leds = be_toint(vm, 3); + int32_t gpio = be_toint(vm, 4); + int32_t rmt = 0; + int32_t neopixel_type = ws2812_grb; + if (argc >= 5 && !(be_isnil(vm, 5))) { + neopixel_type = be_toint(vm, 5); + } + if (neopixel_type < 1) { neopixel_type = 1; } + if (neopixel_type >= neopixel_type_end) { neopixel_type = neopixel_type_end - 1; } + + // store type in attribute `_t` + be_pushint(vm, neopixel_type); + be_setmember(vm, 1, "_t"); + be_pop(vm, 1); + + if (PinUsed(GPIO_WS2812)) { + rmt = 1; // if WS2812 is already configured by Tasmota UI, we switch to RMT1 + } + if (argc >= 6 && !(be_isnil(vm, 6))) { + rmt = be_toint(vm, 6); // if arg5, then RMT channel is specified + } + if (rmt < 0) { rmt = 0; } + if (rmt >= MAX_RMT) { rmt = MAX_RMT - 1; } + void * strip = nullptr; + switch (neopixel_type) { + case ws2812_grb: strip = new neopixel_ws2812_grb_t(leds, gpio, (NeoBusChannel) rmt); + break; + case ws2812_grbw: strip = new neopixel_ws2812_grbw_t(leds, gpio, (NeoBusChannel) rmt); + break; + case sk6812_grb: strip = new neopixel_sk6812_grb_t(leds, gpio, (NeoBusChannel) rmt); + break; + case sk6812_grbw: strip = new neopixel_sk6812_grbw_t(leds, gpio, (NeoBusChannel) rmt); + break; + } + be_pushcomptr(vm, (void*) strip); + be_setmember(vm, 1, "_p"); + be_pop(vm, 1); + be_pushnil(vm); + } else { + // all other commands need a valid neopixelbus pointer + int32_t leds_type = be_get_leds_type(vm); + const void * s = be_get_neopixelbus(vm); // raises an exception if pointer is invalid + // initialize all possible variants + neopixel_ws2812_grb_t * s_ws2812_grb = (leds_type == ws2812_grb) ? (neopixel_ws2812_grb_t*) s : nullptr; + neopixel_ws2812_grbw_t * s_ws2812_grbw = (leds_type == ws2812_grbw) ? (neopixel_ws2812_grbw_t*) s : nullptr; + neopixel_sk6812_grb_t * s_sk6812_grb = (leds_type == sk6812_grb) ? (neopixel_sk6812_grb_t*) s : nullptr; + neopixel_sk6812_grbw_t * s_sk6812_grbw = (leds_type == sk6812_grbw) ? (neopixel_sk6812_grbw_t*) s : nullptr; + + be_pushnil(vm); // push a default `nil` return value + + switch (cmd) { + case 1: // # 01 : begin void -> void + if (s_ws2812_grb) s_ws2812_grb->Begin(); + if (s_ws2812_grbw) s_ws2812_grbw->Begin(); + if (s_sk6812_grb) s_sk6812_grb->Begin(); + if (s_sk6812_grbw) s_sk6812_grbw->Begin(); + break; + case 2: // # 02 : show void -> void + if (s_ws2812_grb) s_ws2812_grb->Show(); + if (s_ws2812_grbw) s_ws2812_grbw->Show(); + if (s_sk6812_grb) s_sk6812_grb->Show(); + if (s_sk6812_grbw) s_sk6812_grbw->Show(); + break; + case 3: // # 03 : CanShow void -> bool + if (s_ws2812_grb) be_pushbool(vm, s_ws2812_grb->CanShow()); + if (s_ws2812_grbw) be_pushbool(vm, s_ws2812_grbw->CanShow()); + if (s_sk6812_grb) be_pushbool(vm, s_sk6812_grb->CanShow()); + if (s_sk6812_grbw) be_pushbool(vm, s_sk6812_grbw->CanShow()); + break; + case 4: // # 04 : IsDirty void -> bool + if (s_ws2812_grb) be_pushbool(vm, s_ws2812_grb->IsDirty()); + if (s_ws2812_grbw) be_pushbool(vm, s_ws2812_grbw->IsDirty()); + if (s_sk6812_grb) be_pushbool(vm, s_sk6812_grb->IsDirty()); + if (s_sk6812_grbw) be_pushbool(vm, s_sk6812_grbw->IsDirty()); + break; + case 5: // # 05 : Dirty void -> void + if (s_ws2812_grb) s_ws2812_grb->Dirty(); + if (s_ws2812_grbw) s_ws2812_grbw->Dirty(); + if (s_sk6812_grb) s_sk6812_grb->Dirty(); + if (s_sk6812_grbw) s_sk6812_grbw->Dirty(); + break; + case 6: // # 06 : Pixels void -> bytes() (mapped to the buffer) + { + size_t pixels_bytes; + if (s_ws2812_grb) pixels_bytes = s_ws2812_grb->PixelsSize(); + if (s_ws2812_grbw) pixels_bytes = s_ws2812_grbw->PixelsSize(); + if (s_sk6812_grb) pixels_bytes = s_sk6812_grb->PixelsSize(); + if (s_sk6812_grbw) pixels_bytes = s_sk6812_grbw->PixelsSize(); + + uint8_t * pixels; + if (s_ws2812_grb) pixels = s_ws2812_grb->Pixels(); + if (s_ws2812_grbw) pixels = s_ws2812_grbw->Pixels(); + if (s_sk6812_grb) pixels = s_sk6812_grb->Pixels(); + if (s_sk6812_grbw) pixels = s_sk6812_grbw->Pixels(); + + be_getbuiltin(vm, "bytes"); + be_pushcomptr(vm, pixels); + be_pushint(vm, pixels_bytes); + be_call(vm, 2); + be_pop(vm, 2); + } + break; + case 7: // # 07 : PixelSize void -> int + if (s_ws2812_grb) be_pushint(vm, s_ws2812_grb->PixelSize()); + if (s_ws2812_grbw) be_pushint(vm, s_ws2812_grbw->PixelSize()); + if (s_sk6812_grb) be_pushint(vm, s_sk6812_grb->PixelSize()); + if (s_sk6812_grbw) be_pushint(vm, s_sk6812_grbw->PixelSize()); + break; + case 8: // # 08 : PixelCount void -> int + if (s_ws2812_grb) be_pushint(vm, s_ws2812_grb->PixelCount()); + if (s_ws2812_grbw) be_pushint(vm, s_ws2812_grbw->PixelCount()); + if (s_sk6812_grb) be_pushint(vm, s_sk6812_grb->PixelCount()); + if (s_sk6812_grbw) be_pushint(vm, s_sk6812_grbw->PixelCount()); + break; + case 9: // # 09 : ClearTo (color:??) -> void + { + uint32_t rgbw = be_toint(vm, 3); + uint8_t w = (rgbw & 0xFF000000) >> 24; + uint8_t r = (rgbw & 0xFF0000) >> 16; + uint8_t g = (rgbw & 0xFF00) >> 8; + uint8_t b = (rgbw & 0xFF); + if (s_ws2812_grb) s_ws2812_grb->ClearTo(RgbColor(r, g, b)); + if (s_ws2812_grbw) s_ws2812_grbw->ClearTo(RgbwColor(r, g, b, 0)); + if (s_sk6812_grb) s_sk6812_grb->ClearTo(RgbColor(r, g, b)); + if (s_sk6812_grbw) s_sk6812_grbw->ClearTo(RgbwColor(r, g, b, 0)); + } + break; + case 10: // # 10 : SetPixelColor (idx:int, color:??) -> void + { + int32_t idx = be_toint(vm, 3); + uint32_t rgbw = be_toint(vm, 4); + uint8_t w = (rgbw & 0xFF000000) >> 24; + uint8_t r = (rgbw & 0xFF0000) >> 16; + uint8_t g = (rgbw & 0xFF00) >> 8; + uint8_t b = (rgbw & 0xFF); + if (s_ws2812_grb) s_ws2812_grb->SetPixelColor(idx, RgbColor(r, g, b)); + if (s_ws2812_grbw) s_ws2812_grbw->SetPixelColor(idx, RgbwColor(r, g, b, 0)); + if (s_sk6812_grb) s_sk6812_grb->SetPixelColor(idx, RgbColor(r, g, b)); + if (s_sk6812_grbw) s_sk6812_grbw->SetPixelColor(idx, RgbwColor(r, g, b, 0)); + } + break; + case 11: // # 11 : GetPixelColor (idx:int) -> color:?? + { + int32_t idx = be_toint(vm, 3); + RgbColor rgb; + + if (s_ws2812_grb) { + RgbColor rgb = s_ws2812_grb->GetPixelColor(idx); + be_pushint(vm, (rgb.R << 16) | (rgb.G << 8) | rgb.B); + } + if (s_ws2812_grbw) { + RgbwColor rgbw = s_ws2812_grbw->GetPixelColor(idx); + be_pushint(vm, (rgbw.W << 24) | (rgb.R << 16) | (rgb.G << 8) | rgb.B); + } + if (s_sk6812_grb) { + RgbColor rgb = s_sk6812_grb->GetPixelColor(idx); + be_pushint(vm, (rgb.R << 16) | (rgb.G << 8) | rgb.B); + } + if (s_sk6812_grbw) { + RgbwColor rgbw = s_sk6812_grbw->GetPixelColor(idx); + be_pushint(vm, (rgbw.W << 24) | (rgb.R << 16) | (rgb.G << 8) | rgb.B); + } + } + break; + // case 20: // # 20 : RotateLeft (rot:int [, first:int, last:int]) -> void + // case 21: // # 21 : RotateRight (rot:int [, first:int, last:int]) -> void + // case 22: // # 22 : ShiftLeft (rot:int [, first:int, last:int]) -> void + // case 23: // # 23 : ShiftRight (rot:int [, first:int, last:int]) -> void + // { + // int32_t rot = be_toint(vm, 3); + // int32_t first = -1; + // int32_t last = -1; + // if (argc >= 5) { + // first = be_toint(vm, 4); + // last = be_toint(vm, 5); + // } + // if (20 == cmd) { + // if (first >= 0) { strip->RotateLeft(rot, first, last); } else { strip->RotateLeft(rot); }; + // } else if (21 == cmd) { + // if (first >= 0) { strip->RotateRight(rot, first, last); } else { strip->RotateRight(rot); }; + // } else if (22 == cmd) { + // if (first >= 0) { strip->ShiftLeft(rot, first, last); } else { strip->ShiftLeft(rot); }; + // } else if (23 == cmd) { + // if (first >= 0) { strip->ShiftRight(rot, first, last); } else { strip->ShiftRight(rot); }; + // } + // } + // break; + default: + break; + } + } + be_return(vm); + } + be_raise(vm, kTypeError, nullptr); + } + +} + +#endif // USE_WS2812 +#endif // USE_BERRY diff --git a/tasmota/xdrv_52_9_berry.ino b/tasmota/xdrv_52_9_berry.ino index 84a7b962a..c2ed977be 100644 --- a/tasmota/xdrv_52_9_berry.ino +++ b/tasmota/xdrv_52_9_berry.ino @@ -780,9 +780,6 @@ bool Xdrv52(uint8_t function) case FUNC_MQTT_DATA: result = callBerryEventDispatcher(PSTR("mqtt_data"), XdrvMailbox.topic, 0, XdrvMailbox.data, XdrvMailbox.data_len); break; - case FUNC_EVERY_50_MSECOND: - callBerryEventDispatcher(PSTR("every_50ms"), nullptr, 0, nullptr); - break; case FUNC_COMMAND: result = DecodeCommand(kBrCommands, BerryCommand); if (!result) { @@ -791,6 +788,9 @@ bool Xdrv52(uint8_t function) break; // Module specific events + case FUNC_EVERY_50_MSECOND: + callBerryEventDispatcher(PSTR("every_50ms"), nullptr, 0, nullptr); + break; case FUNC_EVERY_100_MSECOND: callBerryEventDispatcher(PSTR("every_100ms"), nullptr, 0, nullptr); break; From 8a8724763f239f832e6f320b1de168f9c41c9d67 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Fri, 19 Nov 2021 22:09:35 +0100 Subject: [PATCH 061/185] Berry add animation framework --- lib/libesp32/Berry/default/be_animate_lib.c | 733 ++++++++++++++++++ .../Berry/default/be_leds_animator_lib.c | 525 +++++++------ lib/libesp32/Berry/default/be_modtab.c | 2 + lib/libesp32/Berry/default/be_tasmotalib.c | 98 +++ .../Berry/default/embedded/Animate.be | 184 +++++ .../Berry/default/embedded/Tasmota.be | 48 ++ .../Berry/default/embedded/leds_animator.be | 19 + lib/libesp32/Berry/generate/be_const_strtab.h | 1 + .../Berry/generate/be_const_strtab_def.h | 5 +- .../generate/be_fixed_be_class_tasmota.h | 139 ++-- lib/libesp32/Berry/src/be_solidifylib.c | 22 +- tasmota/berry/leds/rainbow.be | 56 +- 12 files changed, 1508 insertions(+), 324 deletions(-) create mode 100644 lib/libesp32/Berry/default/be_animate_lib.c create mode 100644 lib/libesp32/Berry/default/embedded/Animate.be diff --git a/lib/libesp32/Berry/default/be_animate_lib.c b/lib/libesp32/Berry/default/be_animate_lib.c new file mode 100644 index 000000000..3253d25e5 --- /dev/null +++ b/lib/libesp32/Berry/default/be_animate_lib.c @@ -0,0 +1,733 @@ +/******************************************************************** + * Berry module `animate` + * + * To use: `import animate` + * + *******************************************************************/ +#include "be_constobj.h" + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Animate_rotate_init, /* name */ + be_nested_proto( + 12, /* nstack */ + 5, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 8]) { /* constants */ + /* K0 */ be_nested_string("init", 380752755, 4), + /* K1 */ be_nested_string("closure", 1548407746, 7), + /* K2 */ be_nested_string("code", -114201356, 4), + /* K3 */ be_nested_string("push", -2022703139, 4), + /* K4 */ be_nested_string("animate", -409180496, 7), + /* K5 */ be_nested_string("ins_ramp", 1068049360, 8), + /* K6 */ be_nested_string("ins_goto", 1342843963, 8), + /* K7 */ be_const_int(0), + }), + (be_nested_const_str("init", 380752755, 4)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[28]) { /* code */ + 0x60140003, // 0000 GETGBL R5 G3 + 0x5C180000, // 0001 MOVE R6 R0 + 0x7C140200, // 0002 CALL R5 1 + 0x8C140B00, // 0003 GETMET R5 R5 K0 + 0x7C140200, // 0004 CALL R5 1 + 0x4C140000, // 0005 LDNIL R5 + 0x20140205, // 0006 NE R5 R1 R5 + 0x78160000, // 0007 JMPF R5 #0009 + 0x90020201, // 0008 SETMBR R0 K1 R1 + 0x88140102, // 0009 GETMBR R5 R0 K2 + 0x8C140B03, // 000A GETMET R5 R5 K3 + 0xB81E0800, // 000B GETNGBL R7 K4 + 0x8C1C0F05, // 000C GETMET R7 R7 K5 + 0x5C240400, // 000D MOVE R9 R2 + 0x5C280600, // 000E MOVE R10 R3 + 0x5C2C0800, // 000F MOVE R11 R4 + 0x7C1C0800, // 0010 CALL R7 4 + 0x7C140400, // 0011 CALL R5 2 + 0x88140102, // 0012 GETMBR R5 R0 K2 + 0x8C140B03, // 0013 GETMET R5 R5 K3 + 0xB81E0800, // 0014 GETNGBL R7 K4 + 0x8C1C0F06, // 0015 GETMET R7 R7 K6 + 0x58240007, // 0016 LDCONST R9 K7 + 0x58280007, // 0017 LDCONST R10 K7 + 0x582C0007, // 0018 LDCONST R11 K7 + 0x7C1C0800, // 0019 CALL R7 4 + 0x7C140400, // 001A CALL R5 2 + 0x80000000, // 001B RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Animate_rotate +********************************************************************/ +extern const bclass be_class_Animate_engine; +be_local_class(Animate_rotate, + 0, + &be_class_Animate_engine, + be_nested_map(1, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_nested_key("init", 380752755, 4, -1), be_const_closure(Animate_rotate_init_closure) }, + })), + (be_nested_const_str("Animate_rotate", -787188142, 14)) +); + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Animate_from_to_init, /* name */ + be_nested_proto( + 12, /* nstack */ + 5, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_string("init", 380752755, 4), + /* K1 */ be_nested_string("closure", 1548407746, 7), + /* K2 */ be_nested_string("code", -114201356, 4), + /* K3 */ be_nested_string("push", -2022703139, 4), + /* K4 */ be_nested_string("animate", -409180496, 7), + /* K5 */ be_nested_string("ins_ramp", 1068049360, 8), + }), + (be_nested_const_str("init", 380752755, 4)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[19]) { /* code */ + 0x60140003, // 0000 GETGBL R5 G3 + 0x5C180000, // 0001 MOVE R6 R0 + 0x7C140200, // 0002 CALL R5 1 + 0x8C140B00, // 0003 GETMET R5 R5 K0 + 0x7C140200, // 0004 CALL R5 1 + 0x4C140000, // 0005 LDNIL R5 + 0x20140205, // 0006 NE R5 R1 R5 + 0x78160000, // 0007 JMPF R5 #0009 + 0x90020201, // 0008 SETMBR R0 K1 R1 + 0x88140102, // 0009 GETMBR R5 R0 K2 + 0x8C140B03, // 000A GETMET R5 R5 K3 + 0xB81E0800, // 000B GETNGBL R7 K4 + 0x8C1C0F05, // 000C GETMET R7 R7 K5 + 0x5C240400, // 000D MOVE R9 R2 + 0x5C280600, // 000E MOVE R10 R3 + 0x5C2C0800, // 000F MOVE R11 R4 + 0x7C1C0800, // 0010 CALL R7 4 + 0x7C140400, // 0011 CALL R5 2 + 0x80000000, // 0012 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Animate_from_to +********************************************************************/ +extern const bclass be_class_Animate_engine; +be_local_class(Animate_from_to, + 0, + &be_class_Animate_engine, + be_nested_map(1, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_nested_key("init", 380752755, 4, -1), be_const_closure(Animate_from_to_init_closure) }, + })), + (be_nested_const_str("Animate_from_to", 1699049867, 15)) +); + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Animate_back_forth_init, /* name */ + be_nested_proto( + 12, /* nstack */ + 5, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 9]) { /* constants */ + /* K0 */ be_nested_string("init", 380752755, 4), + /* K1 */ be_nested_string("closure", 1548407746, 7), + /* K2 */ be_nested_string("code", -114201356, 4), + /* K3 */ be_nested_string("push", -2022703139, 4), + /* K4 */ be_nested_string("animate", -409180496, 7), + /* K5 */ be_nested_string("ins_ramp", 1068049360, 8), + /* K6 */ be_const_int(2), + /* K7 */ be_nested_string("ins_goto", 1342843963, 8), + /* K8 */ be_const_int(0), + }), + (be_nested_const_str("init", 380752755, 4)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[37]) { /* code */ + 0x60140003, // 0000 GETGBL R5 G3 + 0x5C180000, // 0001 MOVE R6 R0 + 0x7C140200, // 0002 CALL R5 1 + 0x8C140B00, // 0003 GETMET R5 R5 K0 + 0x7C140200, // 0004 CALL R5 1 + 0x4C140000, // 0005 LDNIL R5 + 0x20140205, // 0006 NE R5 R1 R5 + 0x78160000, // 0007 JMPF R5 #0009 + 0x90020201, // 0008 SETMBR R0 K1 R1 + 0x88140102, // 0009 GETMBR R5 R0 K2 + 0x8C140B03, // 000A GETMET R5 R5 K3 + 0xB81E0800, // 000B GETNGBL R7 K4 + 0x8C1C0F05, // 000C GETMET R7 R7 K5 + 0x5C240400, // 000D MOVE R9 R2 + 0x5C280600, // 000E MOVE R10 R3 + 0x0C2C0906, // 000F DIV R11 R4 K6 + 0x7C1C0800, // 0010 CALL R7 4 + 0x7C140400, // 0011 CALL R5 2 + 0x88140102, // 0012 GETMBR R5 R0 K2 + 0x8C140B03, // 0013 GETMET R5 R5 K3 + 0xB81E0800, // 0014 GETNGBL R7 K4 + 0x8C1C0F05, // 0015 GETMET R7 R7 K5 + 0x5C240600, // 0016 MOVE R9 R3 + 0x5C280400, // 0017 MOVE R10 R2 + 0x0C2C0906, // 0018 DIV R11 R4 K6 + 0x7C1C0800, // 0019 CALL R7 4 + 0x7C140400, // 001A CALL R5 2 + 0x88140102, // 001B GETMBR R5 R0 K2 + 0x8C140B03, // 001C GETMET R5 R5 K3 + 0xB81E0800, // 001D GETNGBL R7 K4 + 0x8C1C0F07, // 001E GETMET R7 R7 K7 + 0x58240008, // 001F LDCONST R9 K8 + 0x58280008, // 0020 LDCONST R10 K8 + 0x582C0008, // 0021 LDCONST R11 K8 + 0x7C1C0800, // 0022 CALL R7 4 + 0x7C140400, // 0023 CALL R5 2 + 0x80000000, // 0024 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Animate_back_forth +********************************************************************/ +extern const bclass be_class_Animate_engine; +be_local_class(Animate_back_forth, + 0, + &be_class_Animate_engine, + be_nested_map(1, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_nested_key("init", 380752755, 4, -1), be_const_closure(Animate_back_forth_init_closure) }, + })), + (be_nested_const_str("Animate_back_forth", 5319526, 18)) +); + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Animate_ins_goto_init, /* name */ + be_nested_proto( + 4, /* nstack */ + 4, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_string("pc_rel", 991921176, 6), + /* K1 */ be_nested_string("pc_abs", 920256495, 6), + /* K2 */ be_nested_string("duration", 799079693, 8), + }), + (be_nested_const_str("init", 380752755, 4)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 4]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x90020202, // 0001 SETMBR R0 K1 R2 + 0x90020403, // 0002 SETMBR R0 K2 R3 + 0x80000000, // 0003 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Animate_ins_goto +********************************************************************/ +be_local_class(Animate_ins_goto, + 3, + NULL, + be_nested_map(4, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_nested_key("pc_rel", 991921176, 6, -1), be_const_var(0) }, + { be_nested_key("duration", 799079693, 8, -1), be_const_var(2) }, + { be_nested_key("pc_abs", 920256495, 6, -1), be_const_var(1) }, + { be_nested_key("init", 380752755, 4, 2), be_const_closure(Animate_ins_goto_init_closure) }, + })), + (be_nested_const_str("Animate_ins_goto", 1667367043, 16)) +); + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Animate_ins_ramp_init, /* name */ + be_nested_proto( + 4, /* nstack */ + 4, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_string("a", -468965076, 1), + /* K1 */ be_nested_string("b", -418632219, 1), + /* K2 */ be_nested_string("duration", 799079693, 8), + }), + (be_nested_const_str("init", 380752755, 4)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 4]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x90020202, // 0001 SETMBR R0 K1 R2 + 0x90020403, // 0002 SETMBR R0 K2 R3 + 0x80000000, // 0003 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Animate_ins_ramp +********************************************************************/ +be_local_class(Animate_ins_ramp, + 3, + NULL, + be_nested_map(4, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_nested_key("a", -468965076, 1, -1), be_const_var(0) }, + { be_nested_key("b", -418632219, 1, 2), be_const_var(1) }, + { be_nested_key("duration", 799079693, 8, -1), be_const_var(2) }, + { be_nested_key("init", 380752755, 4, -1), be_const_closure(Animate_ins_ramp_init_closure) }, + })), + (be_nested_const_str("Animate_ins_ramp", 785058280, 16)) +); + +/******************************************************************** +** Solidified function: is_running +********************************************************************/ +be_local_closure(Animate_engine_is_running, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_string("running", 343848780, 7), + }), + (be_nested_const_str("is_running", -2068120035, 10)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: run +********************************************************************/ +be_local_closure(Animate_engine_run, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_string("tasmota", 424643812, 7), + /* K1 */ be_nested_string("millis", 1214679063, 6), + /* K2 */ be_nested_string("ins_time", -1314721743, 8), + /* K3 */ be_nested_string("running", 343848780, 7), + /* K4 */ be_nested_string("add_driver", 1654458371, 10), + }), + (be_nested_const_str("run", 718098122, 3)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[15]) { /* code */ + 0x4C080000, // 0000 LDNIL R2 + 0x1C080202, // 0001 EQ R2 R1 R2 + 0x780A0003, // 0002 JMPF R2 #0007 + 0xB80A0000, // 0003 GETNGBL R2 K0 + 0x8C080501, // 0004 GETMET R2 R2 K1 + 0x7C080200, // 0005 CALL R2 1 + 0x5C040400, // 0006 MOVE R1 R2 + 0x90020401, // 0007 SETMBR R0 K2 R1 + 0x50080200, // 0008 LDBOOL R2 1 0 + 0x90020602, // 0009 SETMBR R0 K3 R2 + 0xB80A0000, // 000A GETNGBL R2 K0 + 0x8C080504, // 000B GETMET R2 R2 K4 + 0x5C100000, // 000C MOVE R4 R0 + 0x7C080400, // 000D CALL R2 2 + 0x80000000, // 000E RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Animate_engine_init, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 1, /* has sup protos */ + ( &(const struct bproto*[ 1]) { + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_string("Animate next value:", 443143038, 19), + }), + (be_nested_const_str("_anonymous_", 1957281476, 11)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 5]) { /* code */ + 0x60040001, // 0000 GETGBL R1 G1 + 0x58080000, // 0001 LDCONST R2 K0 + 0x5C0C0000, // 0002 MOVE R3 R0 + 0x7C040400, // 0003 CALL R1 2 + 0x80000000, // 0004 RET 0 + }) + ), + }), + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_string("code", -114201356, 4), + /* K1 */ be_nested_string("closure", 1548407746, 7), + /* K2 */ be_nested_string("pc", 1313756516, 2), + /* K3 */ be_const_int(0), + /* K4 */ be_nested_string("ins_time", -1314721743, 8), + /* K5 */ be_nested_string("running", 343848780, 7), + }), + (be_nested_const_str("init", 380752755, 4)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[10]) { /* code */ + 0x60040012, // 0000 GETGBL R1 G18 + 0x7C040000, // 0001 CALL R1 0 + 0x90020001, // 0002 SETMBR R0 K0 R1 + 0x84040000, // 0003 CLOSURE R1 P0 + 0x90020201, // 0004 SETMBR R0 K1 R1 + 0x90020503, // 0005 SETMBR R0 K2 K3 + 0x90020903, // 0006 SETMBR R0 K4 K3 + 0x50040000, // 0007 LDBOOL R1 0 0 + 0x90020A01, // 0008 SETMBR R0 K5 R1 + 0x80000000, // 0009 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: every_50ms +********************************************************************/ +be_local_closure(Animate_engine_every_50ms, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_string("animate", -409180496, 7), + }), + (be_nested_const_str("every_50ms", -1911083288, 10)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 3]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x7C040200, // 0001 CALL R1 1 + 0x80000000, // 0002 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: stop +********************************************************************/ +be_local_closure(Animate_engine_stop, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_string("running", 343848780, 7), + /* K1 */ be_nested_string("tasmota", 424643812, 7), + /* K2 */ be_nested_string("remove_driver", 1030243768, 13), + }), + (be_nested_const_str("stop", -883741979, 4)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 7]) { /* code */ + 0x50040000, // 0000 LDBOOL R1 0 0 + 0x90020001, // 0001 SETMBR R0 K0 R1 + 0xB8060200, // 0002 GETNGBL R1 K1 + 0x8C040302, // 0003 GETMET R1 R1 K2 + 0x5C0C0000, // 0004 MOVE R3 R0 + 0x7C040400, // 0005 CALL R1 2 + 0x80000000, // 0006 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: animate +********************************************************************/ +be_local_closure(Animate_engine_animate, /* name */ + be_nested_proto( + 12, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[21]) { /* constants */ + /* K0 */ be_nested_string("running", 343848780, 7), + /* K1 */ be_nested_string("tasmota", 424643812, 7), + /* K2 */ be_nested_string("millis", 1214679063, 6), + /* K3 */ be_nested_string("ins_time", -1314721743, 8), + /* K4 */ be_nested_string("pc", 1313756516, 2), + /* K5 */ be_nested_string("code", -114201356, 4), + /* K6 */ be_const_int(0), + /* K7 */ be_nested_string("internal_error", -1775809127, 14), + /* K8 */ be_nested_string("Animate pc is out of range", 1854929421, 26), + /* K9 */ be_nested_string("animate", -409180496, 7), + /* K10 */ be_nested_string("ins_ramp", 1068049360, 8), + /* K11 */ be_nested_string("closure", 1548407746, 7), + /* K12 */ be_nested_string("duration", 799079693, 8), + /* K13 */ be_nested_string("scale_uint", -1204156202, 10), + /* K14 */ be_nested_string("a", -468965076, 1), + /* K15 */ be_nested_string("b", -418632219, 1), + /* K16 */ be_const_int(1), + /* K17 */ be_nested_string("ins_goto", 1342843963, 8), + /* K18 */ be_nested_string("pc_rel", 991921176, 6), + /* K19 */ be_nested_string("pc_abs", 920256495, 6), + /* K20 */ be_nested_string("unknown instruction", 1093911841, 19), + }), + (be_nested_const_str("animate", -409180496, 7)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[93]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x740A0000, // 0001 JMPT R2 #0003 + 0x80000400, // 0002 RET 0 + 0x4C080000, // 0003 LDNIL R2 + 0x1C080202, // 0004 EQ R2 R1 R2 + 0x780A0003, // 0005 JMPF R2 #000A + 0xB80A0200, // 0006 GETNGBL R2 K1 + 0x8C080502, // 0007 GETMET R2 R2 K2 + 0x7C080200, // 0008 CALL R2 1 + 0x5C040400, // 0009 MOVE R1 R2 + 0x50080200, // 000A LDBOOL R2 1 0 + 0x780A004F, // 000B JMPF R2 #005C + 0x88080103, // 000C GETMBR R2 R0 K3 + 0x04080202, // 000D SUB R2 R1 R2 + 0x880C0104, // 000E GETMBR R3 R0 K4 + 0x6010000C, // 000F GETGBL R4 G12 + 0x88140105, // 0010 GETMBR R5 R0 K5 + 0x7C100200, // 0011 CALL R4 1 + 0x280C0604, // 0012 GE R3 R3 R4 + 0x780E0002, // 0013 JMPF R3 #0017 + 0x500C0000, // 0014 LDBOOL R3 0 0 + 0x90020003, // 0015 SETMBR R0 K0 R3 + 0x70020044, // 0016 JMP #005C + 0x880C0104, // 0017 GETMBR R3 R0 K4 + 0x140C0706, // 0018 LT R3 R3 K6 + 0x780E0000, // 0019 JMPF R3 #001B + 0xB0060F08, // 001A RAISE 1 K7 K8 + 0x880C0104, // 001B GETMBR R3 R0 K4 + 0x88100105, // 001C GETMBR R4 R0 K5 + 0x940C0803, // 001D GETIDX R3 R4 R3 + 0x6014000F, // 001E GETGBL R5 G15 + 0x5C180600, // 001F MOVE R6 R3 + 0xB81E1200, // 0020 GETNGBL R7 K9 + 0x881C0F0A, // 0021 GETMBR R7 R7 K10 + 0x7C140400, // 0022 CALL R5 2 + 0x7816001B, // 0023 JMPF R5 #0040 + 0x8810010B, // 0024 GETMBR R4 R0 K11 + 0x8814070C, // 0025 GETMBR R5 R3 K12 + 0x14140405, // 0026 LT R5 R2 R5 + 0x7816000C, // 0027 JMPF R5 #0035 + 0xB8160200, // 0028 GETNGBL R5 K1 + 0x8C140B0D, // 0029 GETMET R5 R5 K13 + 0x5C1C0400, // 002A MOVE R7 R2 + 0x58200006, // 002B LDCONST R8 K6 + 0x8824070C, // 002C GETMBR R9 R3 K12 + 0x8828070E, // 002D GETMBR R10 R3 K14 + 0x882C070F, // 002E GETMBR R11 R3 K15 + 0x7C140C00, // 002F CALL R5 6 + 0x5C180800, // 0030 MOVE R6 R4 + 0x5C1C0A00, // 0031 MOVE R7 R5 + 0x7C180200, // 0032 CALL R6 1 + 0x70020027, // 0033 JMP #005C + 0x70020009, // 0034 JMP #003F + 0x5C140800, // 0035 MOVE R5 R4 + 0x8818070F, // 0036 GETMBR R6 R3 K15 + 0x7C140200, // 0037 CALL R5 1 + 0x88140104, // 0038 GETMBR R5 R0 K4 + 0x00140B10, // 0039 ADD R5 R5 K16 + 0x90020805, // 003A SETMBR R0 K4 R5 + 0x8814070C, // 003B GETMBR R5 R3 K12 + 0x04140405, // 003C SUB R5 R2 R5 + 0x04140205, // 003D SUB R5 R1 R5 + 0x90020605, // 003E SETMBR R0 K3 R5 + 0x7002001A, // 003F JMP #005B + 0x6010000F, // 0040 GETGBL R4 G15 + 0x5C140600, // 0041 MOVE R5 R3 + 0xB81A1200, // 0042 GETNGBL R6 K9 + 0x88180D11, // 0043 GETMBR R6 R6 K17 + 0x7C100400, // 0044 CALL R4 2 + 0x78120013, // 0045 JMPF R4 #005A + 0x8810070C, // 0046 GETMBR R4 R3 K12 + 0x14100404, // 0047 LT R4 R2 R4 + 0x78120001, // 0048 JMPF R4 #004B + 0x70020011, // 0049 JMP #005C + 0x7002000D, // 004A JMP #0059 + 0x88100712, // 004B GETMBR R4 R3 K18 + 0x20100906, // 004C NE R4 R4 K6 + 0x78120004, // 004D JMPF R4 #0053 + 0x88100104, // 004E GETMBR R4 R0 K4 + 0x88140712, // 004F GETMBR R5 R3 K18 + 0x00100805, // 0050 ADD R4 R4 R5 + 0x90020804, // 0051 SETMBR R0 K4 R4 + 0x70020001, // 0052 JMP #0055 + 0x88100713, // 0053 GETMBR R4 R3 K19 + 0x90020804, // 0054 SETMBR R0 K4 R4 + 0x8810070C, // 0055 GETMBR R4 R3 K12 + 0x04100404, // 0056 SUB R4 R2 R4 + 0x04100204, // 0057 SUB R4 R1 R4 + 0x90020604, // 0058 SETMBR R0 K3 R4 + 0x70020000, // 0059 JMP #005B + 0xB0060F14, // 005A RAISE 1 K7 K20 + 0x7001FFAD, // 005B JMP #000A + 0x80000000, // 005C RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: autorun +********************************************************************/ +be_local_closure(Animate_engine_autorun, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_string("run", 718098122, 3), + /* K1 */ be_nested_string("tasmota", 424643812, 7), + /* K2 */ be_nested_string("add_driver", 1654458371, 10), + }), + (be_nested_const_str("autorun", 1447527407, 7)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 8]) { /* code */ + 0x8C080100, // 0000 GETMET R2 R0 K0 + 0x5C100200, // 0001 MOVE R4 R1 + 0x7C080400, // 0002 CALL R2 2 + 0xB80A0200, // 0003 GETNGBL R2 K1 + 0x8C080502, // 0004 GETMET R2 R2 K2 + 0x5C100000, // 0005 MOVE R4 R0 + 0x7C080400, // 0006 CALL R2 2 + 0x80000000, // 0007 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Animate_engine +********************************************************************/ +be_local_class(Animate_engine, + 5, + NULL, + be_nested_map(12, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_nested_key("running", 343848780, 7, -1), be_const_var(4) }, + { be_nested_key("is_running", -2068120035, 10, 7), be_const_closure(Animate_engine_is_running_closure) }, + { be_nested_key("run", 718098122, 3, -1), be_const_closure(Animate_engine_run_closure) }, + { be_nested_key("init", 380752755, 4, -1), be_const_closure(Animate_engine_init_closure) }, + { be_nested_key("every_50ms", -1911083288, 10, -1), be_const_closure(Animate_engine_every_50ms_closure) }, + { be_nested_key("stop", -883741979, 4, -1), be_const_closure(Animate_engine_stop_closure) }, + { be_nested_key("pc", 1313756516, 2, 4), be_const_var(2) }, + { be_nested_key("ins_time", -1314721743, 8, -1), be_const_var(3) }, + { be_nested_key("animate", -409180496, 7, 9), be_const_closure(Animate_engine_animate_closure) }, + { be_nested_key("code", -114201356, 4, 6), be_const_var(0) }, + { be_nested_key("closure", 1548407746, 7, -1), be_const_var(1) }, + { be_nested_key("autorun", 1447527407, 7, -1), be_const_closure(Animate_engine_autorun_closure) }, + })), + (be_nested_const_str("Animate_engine", 1498417667, 14)) +); + +/******************************************************************** +** Solidified module: animate +********************************************************************/ +be_local_module(animate, + "animate", + be_nested_map(6, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_nested_key("rotate", -1510671094, 6, 2), be_const_class(be_class_Animate_rotate) }, + { be_nested_key("from_to", 21625507, 7, 3), be_const_class(be_class_Animate_from_to) }, + { be_nested_key("back_forth", -1629925234, 10, -1), be_const_class(be_class_Animate_back_forth) }, + { be_nested_key("ins_goto", 1342843963, 8, -1), be_const_class(be_class_Animate_ins_goto) }, + { be_nested_key("ins_ramp", 1068049360, 8, -1), be_const_class(be_class_Animate_ins_ramp) }, + { be_nested_key("engine", -301606853, 6, -1), be_const_class(be_class_Animate_engine) }, + })) +); +BE_EXPORT_VARIABLE be_define_const_native_module(animate); +/********************************************************************/ diff --git a/lib/libesp32/Berry/default/be_leds_animator_lib.c b/lib/libesp32/Berry/default/be_leds_animator_lib.c index 092d354f6..c5783edb9 100644 --- a/lib/libesp32/Berry/default/be_leds_animator_lib.c +++ b/lib/libesp32/Berry/default/be_leds_animator_lib.c @@ -6,10 +6,60 @@ #ifdef USE_WS2812 +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Leds_animator_init, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 8]) { /* constants */ + /* K0 */ be_nested_string("strip", -48555823, 5), + /* K1 */ be_nested_string("bri", 2112284244, 3), + /* K2 */ be_nested_string("running", 343848780, 7), + /* K3 */ be_nested_string("pixel_count", -1855836553, 11), + /* K4 */ be_nested_string("animators", 279858213, 9), + /* K5 */ be_nested_string("clear", 1550717474, 5), + /* K6 */ be_nested_string("tasmota", 424643812, 7), + /* K7 */ be_nested_string("add_driver", 1654458371, 10), + }), + (be_nested_const_str("init", 380752755, 4)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[18]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x540A0031, // 0001 LDINT R2 50 + 0x90020202, // 0002 SETMBR R0 K1 R2 + 0x50080000, // 0003 LDBOOL R2 0 0 + 0x90020402, // 0004 SETMBR R0 K2 R2 + 0x8C080303, // 0005 GETMET R2 R1 K3 + 0x7C080200, // 0006 CALL R2 1 + 0x90020602, // 0007 SETMBR R0 K3 R2 + 0x60080012, // 0008 GETGBL R2 G18 + 0x7C080000, // 0009 CALL R2 0 + 0x90020802, // 000A SETMBR R0 K4 R2 + 0x8C080105, // 000B GETMET R2 R0 K5 + 0x7C080200, // 000C CALL R2 1 + 0xB80A0C00, // 000D GETNGBL R2 K6 + 0x8C080507, // 000E GETMET R2 R2 K7 + 0x5C100000, // 000F MOVE R4 R0 + 0x7C080400, // 0010 CALL R2 2 + 0x80000000, // 0011 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: set_bri ********************************************************************/ -be_local_closure(set_bri, /* name */ +be_local_closure(Leds_animator_set_bri, /* name */ be_nested_proto( 2, /* nstack */ 2, /* argc */ @@ -33,10 +83,238 @@ be_local_closure(set_bri, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: stop +********************************************************************/ +be_local_closure(Leds_animator_stop, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_string("running", 343848780, 7), + }), + (be_nested_const_str("stop", -883741979, 4)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 3]) { /* code */ + 0x50040000, // 0000 LDBOOL R1 0 0 + 0x90020001, // 0001 SETMBR R0 K0 R1 + 0x80000000, // 0002 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: animate +********************************************************************/ +be_local_closure(Leds_animator_animate, /* name */ + be_nested_proto( + 1, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + (be_nested_const_str("animate", -409180496, 7)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: remove +********************************************************************/ +be_local_closure(Leds_animator_remove, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_string("tasmota", 424643812, 7), + /* K1 */ be_nested_string("remove_driver", 1030243768, 13), + }), + (be_nested_const_str("remove", -611183107, 6)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 5]) { /* code */ + 0xB8060000, // 0000 GETNGBL R1 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x5C0C0000, // 0002 MOVE R3 R0 + 0x7C040400, // 0003 CALL R1 2 + 0x80000000, // 0004 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: every_50ms +********************************************************************/ +be_local_closure(Leds_animator_every_50ms, /* name */ + be_nested_proto( + 6, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 7]) { /* constants */ + /* K0 */ be_nested_string("running", 343848780, 7), + /* K1 */ be_const_int(0), + /* K2 */ be_nested_string("animators", 279858213, 9), + /* K3 */ be_nested_string("is_running", -2068120035, 10), + /* K4 */ be_nested_string("animate", -409180496, 7), + /* K5 */ be_const_int(1), + /* K6 */ be_nested_string("remove", -611183107, 6), + }), + (be_nested_const_str("every_50ms", -1911083288, 10)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[25]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x78060015, // 0001 JMPF R1 #0018 + 0x58040001, // 0002 LDCONST R1 K1 + 0x6008000C, // 0003 GETGBL R2 G12 + 0x880C0102, // 0004 GETMBR R3 R0 K2 + 0x7C080200, // 0005 CALL R2 1 + 0x14080202, // 0006 LT R2 R1 R2 + 0x780A000D, // 0007 JMPF R2 #0016 + 0x88080102, // 0008 GETMBR R2 R0 K2 + 0x94080401, // 0009 GETIDX R2 R2 R1 + 0x8C0C0503, // 000A GETMET R3 R2 K3 + 0x7C0C0200, // 000B CALL R3 1 + 0x780E0003, // 000C JMPF R3 #0011 + 0x8C0C0504, // 000D GETMET R3 R2 K4 + 0x7C0C0200, // 000E CALL R3 1 + 0x00040305, // 000F ADD R1 R1 K5 + 0x70020003, // 0010 JMP #0015 + 0x880C0102, // 0011 GETMBR R3 R0 K2 + 0x8C0C0706, // 0012 GETMET R3 R3 K6 + 0x5C140200, // 0013 MOVE R5 R1 + 0x7C0C0400, // 0014 CALL R3 2 + 0x7001FFEC, // 0015 JMP #0003 + 0x8C080104, // 0016 GETMET R2 R0 K4 + 0x7C080200, // 0017 CALL R2 1 + 0x80000000, // 0018 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_bri +********************************************************************/ +be_local_closure(Leds_animator_get_bri, /* name */ + be_nested_proto( + 3, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_string("bri", 2112284244, 3), + }), + (be_nested_const_str("get_bri", 2041809895, 7)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 2]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x80040400, // 0001 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: start +********************************************************************/ +be_local_closure(Leds_animator_start, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_string("running", 343848780, 7), + }), + (be_nested_const_str("start", 1697318111, 5)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 3]) { /* code */ + 0x50040200, // 0000 LDBOOL R1 1 0 + 0x90020001, // 0001 SETMBR R0 K0 R1 + 0x80000000, // 0002 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: add_anim +********************************************************************/ +be_local_closure(Leds_animator_add_anim, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_string("animators", 279858213, 9), + /* K1 */ be_nested_string("push", -2022703139, 4), + /* K2 */ be_nested_string("run", 718098122, 3), + }), + (be_nested_const_str("add_anim", -314304628, 8)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 7]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x5C100200, // 0002 MOVE R4 R1 + 0x7C080400, // 0003 CALL R2 2 + 0x8C080302, // 0004 GETMET R2 R1 K2 + 0x7C080200, // 0005 CALL R2 1 + 0x80000000, // 0006 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: clear ********************************************************************/ -be_local_closure(clear, /* name */ +be_local_closure(Leds_animator_clear, /* name */ be_nested_proto( 3, /* nstack */ 1, /* argc */ @@ -66,242 +344,29 @@ be_local_closure(clear, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: get_bri -********************************************************************/ -be_local_closure(get_bri, /* name */ - be_nested_proto( - 3, /* nstack */ - 2, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_string("bri", 2112284244, 3), - }), - (be_nested_const_str("get_bri", 2041809895, 7)), - ((bstring*) &be_const_str_input), - ( &(const binstruction[ 2]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x80040400, // 0001 RET 1 R2 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: every_50ms -********************************************************************/ -be_local_closure(every_50ms, /* name */ - be_nested_proto( - 3, /* nstack */ - 1, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_string("running", 343848780, 7), - /* K1 */ be_nested_string("animate", -409180496, 7), - }), - (be_nested_const_str("every_50ms", -1911083288, 10)), - ((bstring*) &be_const_str_input), - ( &(const binstruction[ 5]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x78060001, // 0001 JMPF R1 #0004 - 0x8C040101, // 0002 GETMET R1 R0 K1 - 0x7C040200, // 0003 CALL R1 1 - 0x80000000, // 0004 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: stop -********************************************************************/ -be_local_closure(stop, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_string("running", 343848780, 7), - }), - (be_nested_const_str("stop", -883741979, 4)), - ((bstring*) &be_const_str_input), - ( &(const binstruction[ 3]) { /* code */ - 0x50040000, // 0000 LDBOOL R1 0 0 - 0x90020001, // 0001 SETMBR R0 K0 R1 - 0x80000000, // 0002 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: remove -********************************************************************/ -be_local_closure(remove, /* name */ - be_nested_proto( - 4, /* nstack */ - 1, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_string("tasmota", 424643812, 7), - /* K1 */ be_nested_string("remove_driver", 1030243768, 13), - }), - (be_nested_const_str("remove", -611183107, 6)), - ((bstring*) &be_const_str_input), - ( &(const binstruction[ 5]) { /* code */ - 0xB8060000, // 0000 GETNGBL R1 K0 - 0x8C040301, // 0001 GETMET R1 R1 K1 - 0x5C0C0000, // 0002 MOVE R3 R0 - 0x7C040400, // 0003 CALL R1 2 - 0x80000000, // 0004 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: start -********************************************************************/ -be_local_closure(start, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_string("running", 343848780, 7), - }), - (be_nested_const_str("start", 1697318111, 5)), - ((bstring*) &be_const_str_input), - ( &(const binstruction[ 3]) { /* code */ - 0x50040200, // 0000 LDBOOL R1 1 0 - 0x90020001, // 0001 SETMBR R0 K0 R1 - 0x80000000, // 0002 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(init, /* name */ - be_nested_proto( - 5, /* nstack */ - 2, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 7]) { /* constants */ - /* K0 */ be_nested_string("strip", -48555823, 5), - /* K1 */ be_nested_string("bri", 2112284244, 3), - /* K2 */ be_nested_string("running", 343848780, 7), - /* K3 */ be_nested_string("pixel_count", -1855836553, 11), - /* K4 */ be_nested_string("clear", 1550717474, 5), - /* K5 */ be_nested_string("tasmota", 424643812, 7), - /* K6 */ be_nested_string("add_driver", 1654458371, 10), - }), - (be_nested_const_str("init", 380752755, 4)), - ((bstring*) &be_const_str_input), - ( &(const binstruction[15]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x540A0031, // 0001 LDINT R2 50 - 0x90020202, // 0002 SETMBR R0 K1 R2 - 0x50080000, // 0003 LDBOOL R2 0 0 - 0x90020402, // 0004 SETMBR R0 K2 R2 - 0x8C080303, // 0005 GETMET R2 R1 K3 - 0x7C080200, // 0006 CALL R2 1 - 0x90020602, // 0007 SETMBR R0 K3 R2 - 0x8C080104, // 0008 GETMET R2 R0 K4 - 0x7C080200, // 0009 CALL R2 1 - 0xB80A0A00, // 000A GETNGBL R2 K5 - 0x8C080506, // 000B GETMET R2 R2 K6 - 0x5C100000, // 000C MOVE R4 R0 - 0x7C080400, // 000D CALL R2 2 - 0x80000000, // 000E RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: animate -********************************************************************/ -be_local_closure(animate, /* name */ - be_nested_proto( - 1, /* nstack */ - 1, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ - (be_nested_const_str("animate", -409180496, 7)), - ((bstring*) &be_const_str_input), - ( &(const binstruction[ 1]) { /* code */ - 0x80000000, // 0000 RET 0 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified class: Leds_animator ********************************************************************/ be_local_class(Leds_animator, - 4, + 5, NULL, - be_nested_map(13, + be_nested_map(15, ( (struct bmapnode*) &(const bmapnode[]) { - { be_nested_key("set_bri", -1505848517, 7, 9), be_const_closure(set_bri_closure) }, - { be_nested_key("clear", 1550717474, 5, -1), be_const_closure(clear_closure) }, + { be_nested_key("init", 380752755, 4, 7), be_const_closure(Leds_animator_init_closure) }, + { be_nested_key("set_bri", -1505848517, 7, -1), be_const_closure(Leds_animator_set_bri_closure) }, + { be_nested_key("stop", -883741979, 4, -1), be_const_closure(Leds_animator_stop_closure) }, + { be_nested_key("strip", -48555823, 5, 4), be_const_var(0) }, + { be_nested_key("animators", 279858213, 9, 12), be_const_var(4) }, + { be_nested_key("animate", -409180496, 7, -1), be_const_closure(Leds_animator_animate_closure) }, + { be_nested_key("remove", -611183107, 6, -1), be_const_closure(Leds_animator_remove_closure) }, { be_nested_key("running", 343848780, 7, -1), be_const_var(3) }, - { be_nested_key("get_bri", 2041809895, 7, -1), be_const_closure(get_bri_closure) }, - { be_nested_key("every_50ms", -1911083288, 10, -1), be_const_closure(every_50ms_closure) }, - { be_nested_key("bri", 2112284244, 3, 0), be_const_var(2) }, - { be_nested_key("stop", -883741979, 4, 11), be_const_closure(stop_closure) }, - { be_nested_key("remove", -611183107, 6, 1), be_const_closure(remove_closure) }, - { be_nested_key("start", 1697318111, 5, 3), be_const_closure(start_closure) }, - { be_nested_key("strip", -48555823, 5, -1), be_const_var(0) }, + { be_nested_key("every_50ms", -1911083288, 10, -1), be_const_closure(Leds_animator_every_50ms_closure) }, + { be_nested_key("bri", 2112284244, 3, 6), be_const_var(2) }, + { be_nested_key("get_bri", 2041809895, 7, -1), be_const_closure(Leds_animator_get_bri_closure) }, + { be_nested_key("start", 1697318111, 5, -1), be_const_closure(Leds_animator_start_closure) }, + { be_nested_key("add_anim", -314304628, 8, 13), be_const_closure(Leds_animator_add_anim_closure) }, { be_nested_key("pixel_count", -1855836553, 11, -1), be_const_var(1) }, - { be_nested_key("init", 380752755, 4, -1), be_const_closure(init_closure) }, - { be_nested_key("animate", -409180496, 7, 4), be_const_closure(animate_closure) }, + { be_nested_key("clear", 1550717474, 5, 1), be_const_closure(Leds_animator_clear_closure) }, })), (be_nested_const_str("Leds_animator", 142168673, 13)) ); diff --git a/lib/libesp32/Berry/default/be_modtab.c b/lib/libesp32/Berry/default/be_modtab.c index df2b93843..5c704b142 100644 --- a/lib/libesp32/Berry/default/be_modtab.c +++ b/lib/libesp32/Berry/default/be_modtab.c @@ -36,6 +36,7 @@ be_extern_native_module(webserver); be_extern_native_module(flash); be_extern_native_module(path); be_extern_native_module(unishox); +be_extern_native_module(animate); #ifdef USE_LVGL be_extern_native_module(lv); #endif // USE_LVGL @@ -103,6 +104,7 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = { #ifdef USE_UNISHOX_COMPRESSION &be_native_module(unishox), #endif // USE_UNISHOX_COMPRESSION + &be_native_module(animate), #ifdef USE_LVGL &be_native_module(lv), diff --git a/lib/libesp32/Berry/default/be_tasmotalib.c b/lib/libesp32/Berry/default/be_tasmotalib.c index dc07a8562..671e0d942 100644 --- a/lib/libesp32/Berry/default/be_tasmotalib.c +++ b/lib/libesp32/Berry/default/be_tasmotalib.c @@ -1859,6 +1859,102 @@ be_local_closure(exec_cmd, /* name */ ); /*******************************************************************/ +/******************************************************************** +** Solidified function: hs2rgb +********************************************************************/ +be_local_closure(hs2rgb, /* name */ + be_nested_proto( + 17, /* nstack */ + 3, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_const_int(0), + /* K1 */ be_nested_string("tasmota", 424643812, 7), + /* K2 */ be_nested_string("scale_uint", -1204156202, 10), + /* K3 */ be_const_int(1), + /* K4 */ be_const_int(2), + /* K5 */ be_const_int(3), + }), + (be_nested_const_str("hs2rgb", 1040816349, 6)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[68]) { /* code */ + 0x4C0C0000, // 0000 LDNIL R3 + 0x1C0C0403, // 0001 EQ R3 R2 R3 + 0x780E0000, // 0002 JMPF R3 #0004 + 0x540A00FE, // 0003 LDINT R2 255 + 0x540E00FE, // 0004 LDINT R3 255 + 0x541200FE, // 0005 LDINT R4 255 + 0x541600FE, // 0006 LDINT R5 255 + 0x541A0167, // 0007 LDINT R6 360 + 0x10040206, // 0008 MOD R1 R1 R6 + 0x24180500, // 0009 GT R6 R2 K0 + 0x781A0031, // 000A JMPF R6 #003D + 0x541A003B, // 000B LDINT R6 60 + 0x0C180206, // 000C DIV R6 R1 R6 + 0x541E003B, // 000D LDINT R7 60 + 0x101C0207, // 000E MOD R7 R1 R7 + 0x542200FE, // 000F LDINT R8 255 + 0x04201002, // 0010 SUB R8 R8 R2 + 0xB8260200, // 0011 GETNGBL R9 K1 + 0x8C241302, // 0012 GETMET R9 R9 K2 + 0x5C2C0E00, // 0013 MOVE R11 R7 + 0x58300000, // 0014 LDCONST R12 K0 + 0x5436003B, // 0015 LDINT R13 60 + 0x543A00FE, // 0016 LDINT R14 255 + 0x5C3C1000, // 0017 MOVE R15 R8 + 0x7C240C00, // 0018 CALL R9 6 + 0xB82A0200, // 0019 GETNGBL R10 K1 + 0x8C281502, // 001A GETMET R10 R10 K2 + 0x5C300E00, // 001B MOVE R12 R7 + 0x58340000, // 001C LDCONST R13 K0 + 0x543A003B, // 001D LDINT R14 60 + 0x5C3C1000, // 001E MOVE R15 R8 + 0x544200FE, // 001F LDINT R16 255 + 0x7C280C00, // 0020 CALL R10 6 + 0x1C2C0D00, // 0021 EQ R11 R6 K0 + 0x782E0002, // 0022 JMPF R11 #0026 + 0x5C141400, // 0023 MOVE R5 R10 + 0x5C101000, // 0024 MOVE R4 R8 + 0x70020016, // 0025 JMP #003D + 0x1C2C0D03, // 0026 EQ R11 R6 K3 + 0x782E0002, // 0027 JMPF R11 #002B + 0x5C0C1200, // 0028 MOVE R3 R9 + 0x5C101000, // 0029 MOVE R4 R8 + 0x70020011, // 002A JMP #003D + 0x1C2C0D04, // 002B EQ R11 R6 K4 + 0x782E0002, // 002C JMPF R11 #0030 + 0x5C0C1000, // 002D MOVE R3 R8 + 0x5C101400, // 002E MOVE R4 R10 + 0x7002000C, // 002F JMP #003D + 0x1C2C0D05, // 0030 EQ R11 R6 K5 + 0x782E0002, // 0031 JMPF R11 #0035 + 0x5C0C1000, // 0032 MOVE R3 R8 + 0x5C141200, // 0033 MOVE R5 R9 + 0x70020007, // 0034 JMP #003D + 0x542E0003, // 0035 LDINT R11 4 + 0x1C2C0C0B, // 0036 EQ R11 R6 R11 + 0x782E0002, // 0037 JMPF R11 #003B + 0x5C0C1400, // 0038 MOVE R3 R10 + 0x5C141000, // 0039 MOVE R5 R8 + 0x70020001, // 003A JMP #003D + 0x5C141000, // 003B MOVE R5 R8 + 0x5C101200, // 003C MOVE R4 R9 + 0x541A000F, // 003D LDINT R6 16 + 0x38180606, // 003E SHL R6 R3 R6 + 0x541E0007, // 003F LDINT R7 8 + 0x381C0A07, // 0040 SHL R7 R5 R7 + 0x30180C07, // 0041 OR R6 R6 R7 + 0x30180C04, // 0042 OR R6 R6 R4 + 0x80040C00, // 0043 RET 1 R6 + }) + ) +); +/*******************************************************************/ #include "../generate/be_fixed_be_class_tasmota.h" @@ -1954,6 +2050,8 @@ class be_class_tasmota (scope: global, name: Tasmota) { wire_scan, closure(wire_scan_closure) time_str, closure(time_str_closure) + hs2rgb, closure(hs2rgb_closure) + cb_dispatch, closure(cb_dispatch_closure) gen_cb, closure(gen_cb_closure) diff --git a/lib/libesp32/Berry/default/embedded/Animate.be b/lib/libesp32/Berry/default/embedded/Animate.be new file mode 100644 index 000000000..6f4f28fcc --- /dev/null +++ b/lib/libesp32/Berry/default/embedded/Animate.be @@ -0,0 +1,184 @@ +# +# class Animate +# +# Animation framework +# + +animate = module("animate") + +# state-machine: from val a to b +class Animate_ins_ramp + var a # starting value + var b # end value + var duration # duration in milliseconds + + def init(a,b,duration) + self.a = a + self.b = b + self.duration = duration + end +end +animate.ins_ramp = Animate_ins_ramp + +# state-machine: pause and goto +class Animate_ins_goto + var pc_rel # relative PC, -1 previous instruction, 1 next instruction, 0 means see pc_abs + var pc_abs # absolute PC, only if pc_rel == 0, address if next instruction + var duration # pause in milliseconds before goto, -1 means infinite (state-machine can be changed externally) + + def init(pc_rel, pc_abs, duration) + self.pc_rel = pc_rel + self.pc_abs = pc_abs + self.duration = duration + end +end +animate.ins_goto = Animate_ins_goto + +class Animate_engine + var code # array of state-machine instructions + var closure # closure to call with the new value + var pc # program-counter + var ins_time # absolute time when the current instruction started + var running # is the animation running? allows fast return + + def init() + self.code = [] + self.closure = def (v) print("Animate next value:", v) end # default to debug function + self.pc = 0 # start at instruction 0 + self.ins_time = 0 + self.running = false # not running by default + # + end + + # run but needs external calls to `animate()` + def run(cur_time) + if cur_time == nil cur_time = tasmota.millis() end + self.ins_time = cur_time + + self.running = true + tasmota.add_driver(self) + end + + # runs autonomously in the Tasmota event loop + def autorun(cur_time) + self.run(cur_time) + tasmota.add_driver(self) + end + + def stop() + self.running = false + tasmota.remove_driver(self) + end + + def is_running() + return self.running + end + + def every_50ms() + self.animate() + end + + def animate(cur_time) # time in milliseconds, optional, defaults to `tasmota.millis()` + if !self.running return end + if cur_time == nil cur_time = tasmota.millis() end + # run through instructions + while true + var sub_index = cur_time - self.ins_time # time since the beginning of current instruction + # + # make sure PC is valid + if self.pc >= size(self.code) + self.running = false + break + end + # + if self.pc < 0 raise "internal_error", "Animate pc is out of range" end + var ins = self.code[self.pc] + + # Instruction Ramp + if isinstance(ins, animate.ins_ramp) + var f = self.closure # assign to a local variable to not call a method + if sub_index < ins.duration + # we're still in the ramp + var v = tasmota.scale_uint(sub_index, 0, ins.duration, ins.a, ins.b) + # call closure + f(v) # call closure, need try? TODO + break + else + f(ins.b) # set to last value + self.pc += 1 # next instruction + self.ins_time = cur_time - (sub_index - ins.duration) + end + + # Instruction Goto + elif isinstance(ins, animate.ins_goto) + if sub_index < ins.duration + break + else + if ins.pc_rel != 0 + self.pc += ins.pc_rel + else + self.pc = ins.pc_abs + end + self.ins_time = cur_time - (sub_index - ins.duration) + end + + # Invalid + else + raise "internal_error", "unknown instruction" + end + end + + end +end +animate.engine = Animate_engine + +class Animate_from_to : Animate_engine + + def init(closure, from, to, duration) + super(self).init() + if closure != nil self.closure = closure end + self.code.push(animate.ins_ramp(from, to, duration)) + end + +end +animate.from_to = Animate_from_to + +#- +a=Animate_from_to(nil, 0, 100, 5000) +a.autorun() +-# + +class Animate_rotate : Animate_engine + + def init(closure, from, to, duration) + super(self).init() + if closure != nil self.closure = closure end + self.code.push(animate.ins_ramp(from, to, duration)) + self.code.push(animate.ins_goto(0, 0, 0)) # goto abs pc = 0 without any pause + end + +end +animate.rotate = Animate_rotate + +#- +a=Animate_rotate(nil, 0, 100, 5000) +a.autorun() +-# + +class Animate_back_forth : Animate_engine + + def init(closure, from, to, duration) + super(self).init() + if closure != nil self.closure = closure end + self.code.push(animate.ins_ramp(from, to, duration / 2)) + self.code.push(animate.ins_ramp(to, from, duration / 2)) + self.code.push(animate.ins_goto(0, 0, 0)) # goto abs pc = 0 without any pause + end + +end +animate.back_forth = Animate_back_forth + +#- +a=Animate_back_forth(nil, 0, 100, 5000) +a.autorun() +-# diff --git a/lib/libesp32/Berry/default/embedded/Tasmota.be b/lib/libesp32/Berry/default/embedded/Tasmota.be index e1d7ef10e..97624c49c 100644 --- a/lib/libesp32/Berry/default/embedded/Tasmota.be +++ b/lib/libesp32/Berry/default/embedded/Tasmota.be @@ -509,4 +509,52 @@ class Tasmota raise "internal_error", "No callback available" end + #- convert hue/sat to rgb -# + #- hue:int in range 0..359 -# + #- sat:int (optional) in range 0..255 -# + #- returns int: 0xRRGGBB -# + def hs2rgb(hue,sat) + if sat == nil sat = 255 end + var r = 255 # default to white + var b = 255 + var g = 255 + # we take brightness at 100%, brightness should be set separately + hue = hue % 360 # normalize to 0..359 + + if sat > 0 + var i = hue / 60 # quadrant 0..5 + var f = hue % 60 # 0..59 + var p = 255 - sat + var q = tasmota.scale_uint(f, 0, 60, 255, p) # 0..59 + var t = tasmota.scale_uint(f, 0, 60, p, 255) + + if i == 0 + # r = 255 + g = t + b = p + elif i == 1 + r = q + # g = 255 + b = p + elif i == 2 + r = p + #g = 255 + b = t + elif i == 3 + r = p + g = q + #b = 255 + elif i == 4 + r = t + g = p + #b = 255 + else + #r = 255 + g = p + b = q + end + end + + return (r << 16) | (g << 8) | b + end end diff --git a/lib/libesp32/Berry/default/embedded/leds_animator.be b/lib/libesp32/Berry/default/embedded/leds_animator.be index c57fd87bf..1ed25b491 100644 --- a/lib/libesp32/Berry/default/embedded/leds_animator.be +++ b/lib/libesp32/Berry/default/embedded/leds_animator.be @@ -5,18 +5,25 @@ class Leds_animator var pixel_count # number of pixels in the strip var bri # brightness of the animation, 0..100, default 50 var running # is the animation running + var animators # animators list def init(strip) self.strip = strip self.bri = 50 # percentage of brightness 0..100 self.running = false self.pixel_count = strip.pixel_count() + self.animators = [] # self.clear() # clear all leds first # tasmota.add_driver(self) end + def add_anim(anim) + self.animators.push(anim) + anim.run() # start the animator + end + def clear() self.stop() self.strip.clear() @@ -37,6 +44,18 @@ class Leds_animator def every_50ms() if self.running + # run animators first + var i = 0 + while i < size(self.animators) + var anim = self.animators[i] + if anim.is_running() + anim.animate() + i += 1 + else + self.animators.remove(i) # remove any finished animator + end + end + # tirgger animate and display self.animate() end end diff --git a/lib/libesp32/Berry/generate/be_const_strtab.h b/lib/libesp32/Berry/generate/be_const_strtab.h index c9aafc561..718eac65c 100644 --- a/lib/libesp32/Berry/generate/be_const_strtab.h +++ b/lib/libesp32/Berry/generate/be_const_strtab.h @@ -84,6 +84,7 @@ extern const bcstring be_const_str_false; extern const bcstring be_const_str_add_rule; extern const bcstring be_const_str_setbits; extern const bcstring be_const_str_write_file; +extern const bcstring be_const_str_hs2rgb; extern const bcstring be_const_str_SERIAL_8O1; extern const bcstring be_const_str_wd; extern const bcstring be_const_str_wire_scan; diff --git a/lib/libesp32/Berry/generate/be_const_strtab_def.h b/lib/libesp32/Berry/generate/be_const_strtab_def.h index f031878a3..aed550fdc 100644 --- a/lib/libesp32/Berry/generate/be_const_strtab_def.h +++ b/lib/libesp32/Berry/generate/be_const_strtab_def.h @@ -84,6 +84,7 @@ be_define_const_str(false, "false", 184981848u, 62, 5, NULL); be_define_const_str(add_rule, "add_rule", 596540743u, 0, 8, &be_const_str_setbits); be_define_const_str(setbits, "setbits", 2762408167u, 0, 7, &be_const_str_write_file); be_define_const_str(write_file, "write_file", 3177658879u, 0, 10, NULL); +be_define_const_str(hs2rgb, "hs2rgb", 1040816349u, 0, 6, NULL); be_define_const_str(SERIAL_8O1, "SERIAL_8O1", 289122742u, 0, 10, &be_const_str_wd); be_define_const_str(wd, "wd", 1531424278u, 0, 2, &be_const_str_wire_scan); be_define_const_str(wire_scan, "wire_scan", 2671275880u, 0, 9, NULL); @@ -391,7 +392,7 @@ static const bstring* const m_string_table[] = { (const bstring *)&be_const_str_chars_in_string, (const bstring *)&be_const_str_add_rule, NULL, - NULL, + (const bstring *)&be_const_str_hs2rgb, (const bstring *)&be_const_str_SERIAL_8O1, (const bstring *)&be_const_str_AudioFileSourceFS, (const bstring *)&be_const_str_AudioGenerator, @@ -512,6 +513,6 @@ static const bstring* const m_string_table[] = { static const struct bconststrtab m_const_string_table = { .size = 162, - .count = 324, + .count = 325, .table = m_string_table }; diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_tasmota.h b/lib/libesp32/Berry/generate/be_fixed_be_class_tasmota.h index a61b9a363..6a5f58838 100644 --- a/lib/libesp32/Berry/generate/be_fixed_be_class_tasmota.h +++ b/lib/libesp32/Berry/generate/be_fixed_be_class_tasmota.h @@ -1,87 +1,88 @@ #include "be_constobj.h" static be_define_const_map_slots(be_class_tasmota_map) { - { be_const_key(exec_rules, 20), be_const_closure(exec_rules_closure) }, - { be_const_key(publish_result, 75), be_const_func(l_publish_result) }, - { be_const_key(scale_uint, -1), be_const_func(l_scaleuint) }, - { be_const_key(strftime, 6), be_const_func(l_strftime) }, - { be_const_key(remove_driver, -1), be_const_closure(remove_driver_closure) }, - { be_const_key(get_free_heap, -1), be_const_func(l_getFreeHeap) }, - { be_const_key(time_dump, -1), be_const_func(l_time_dump) }, - { be_const_key(add_driver, 37), be_const_closure(add_driver_closure) }, - { be_const_key(find_op, -1), be_const_closure(find_op_closure) }, - { be_const_key(arch, 38), be_const_func(l_arch) }, - { be_const_key(eth, 26), be_const_func(l_eth) }, - { be_const_key(response_append, -1), be_const_func(l_respAppend) }, - { be_const_key(_timers, -1), be_const_var(0) }, - { be_const_key(try_rule, -1), be_const_closure(try_rule_closure) }, - { be_const_key(_settings_ptr, -1), be_const_comptr(&Settings) }, - { be_const_key(resp_cmnd_error, -1), be_const_func(l_respCmndError) }, + { be_const_key(chars_in_string, 62), be_const_closure(chars_in_string_closure) }, { be_const_key(publish, -1), be_const_func(l_publish) }, - { be_const_key(time_reached, 32), be_const_func(l_timereached) }, - { be_const_key(_get_cb, -1), be_const_func(l_get_cb) }, - { be_const_key(wire1, 27), be_const_var(1) }, - { be_const_key(rtc, 43), be_const_func(l_rtc) }, - { be_const_key(web_send_decimal, -1), be_const_func(l_webSendDecimal) }, - { be_const_key(cmd_res, -1), be_const_var(2) }, - { be_const_key(add_rule, -1), be_const_closure(add_rule_closure) }, - { be_const_key(delay, 40), be_const_func(l_delay) }, - { be_const_key(_global_addr, -1), be_const_comptr(&TasmotaGlobal) }, - { be_const_key(set_light, -1), be_const_closure(set_light_closure) }, - { be_const_key(add_cmd, 74), be_const_closure(add_cmd_closure) }, - { be_const_key(global, -1), be_const_var(3) }, - { be_const_key(get_power, -1), be_const_func(l_getpower) }, - { be_const_key(wire2, -1), be_const_var(4) }, - { be_const_key(cmd, -1), be_const_closure(cmd_closure) }, - { be_const_key(get_option, 48), be_const_func(l_getoption) }, + { be_const_key(try_rule, 5), be_const_closure(try_rule_closure) }, + { be_const_key(_settings_ptr, -1), be_const_comptr(&Settings) }, + { be_const_key(get_free_heap, 43), be_const_func(l_getFreeHeap) }, + { be_const_key(eth, 55), be_const_func(l_eth) }, { be_const_key(set_power, -1), be_const_func(l_setpower) }, - { be_const_key(wd, 28), be_const_var(5) }, - { be_const_key(remove_timer, -1), be_const_closure(remove_timer_closure) }, - { be_const_key(wire_scan, 61), be_const_closure(wire_scan_closure) }, - { be_const_key(_settings_def, -1), be_const_comptr(&be_tasmota_settings_struct) }, - { be_const_key(exec_tele, 69), be_const_closure(exec_tele_closure) }, - { be_const_key(gen_cb, -1), be_const_closure(gen_cb_closure) }, - { be_const_key(chars_in_string, 66), be_const_closure(chars_in_string_closure) }, - { be_const_key(log, -1), be_const_func(l_logInfo) }, - { be_const_key(find_key_i, -1), be_const_closure(find_key_i_closure) }, - { be_const_key(get_light, -1), be_const_closure(get_light_closure) }, - { be_const_key(time_str, -1), be_const_closure(time_str_closure) }, - { be_const_key(_rules, 73), be_const_var(6) }, - { be_const_key(remove_cmd, 50), be_const_closure(remove_cmd_closure) }, - { be_const_key(_cb, -1), be_const_var(7) }, - { be_const_key(_ccmd, -1), be_const_var(8) }, - { be_const_key(i2c_enabled, 53), be_const_func(l_i2cenabled) }, - { be_const_key(resp_cmnd_str, -1), be_const_func(l_respCmndStr) }, - { be_const_key(init, -1), be_const_closure(init_closure) }, - { be_const_key(save, 10), be_const_func(l_save) }, - { be_const_key(set_timer, -1), be_const_closure(set_timer_closure) }, - { be_const_key(resp_cmnd, -1), be_const_func(l_respCmnd) }, - { be_const_key(resp_cmnd_done, -1), be_const_func(l_respCmndDone) }, - { be_const_key(get_switch, 21), be_const_func(l_getswitch) }, - { be_const_key(load, -1), be_const_closure(load_closure) }, - { be_const_key(_cmd, 72), be_const_func(l_cmd) }, + { be_const_key(exec_rules, -1), be_const_closure(exec_rules_closure) }, + { be_const_key(i2c_enabled, -1), be_const_func(l_i2cenabled) }, { be_const_key(event, -1), be_const_closure(event_closure) }, - { be_const_key(run_deferred, -1), be_const_closure(run_deferred_closure) }, - { be_const_key(web_send, 1), be_const_func(l_webSend) }, + { be_const_key(hs2rgb, -1), be_const_closure(hs2rgb_closure) }, + { be_const_key(time_str, 56), be_const_closure(time_str_closure) }, + { be_const_key(gen_cb, -1), be_const_closure(gen_cb_closure) }, + { be_const_key(response_append, 1), be_const_func(l_respAppend) }, + { be_const_key(set_light, -1), be_const_closure(set_light_closure) }, + { be_const_key(remove_driver, 47), be_const_closure(remove_driver_closure) }, + { be_const_key(yield, 37), be_const_func(l_yield) }, + { be_const_key(exec_cmd, 2), be_const_closure(exec_cmd_closure) }, + { be_const_key(rtc, 14), be_const_func(l_rtc) }, + { be_const_key(cmd_res, -1), be_const_var(0) }, + { be_const_key(resp_cmnd_str, -1), be_const_func(l_respCmndStr) }, + { be_const_key(set_timer, -1), be_const_closure(set_timer_closure) }, + { be_const_key(resp_cmnd_error, -1), be_const_func(l_respCmndError) }, + { be_const_key(exec_tele, -1), be_const_closure(exec_tele_closure) }, + { be_const_key(_global_def, -1), be_const_comptr(&be_tasmota_global_struct) }, + { be_const_key(global, 51), be_const_var(1) }, + { be_const_key(_global_addr, -1), be_const_comptr(&TasmotaGlobal) }, + { be_const_key(add_driver, 12), be_const_closure(add_driver_closure) }, + { be_const_key(_timers, 53), be_const_var(2) }, + { be_const_key(_cb, 71), be_const_var(3) }, + { be_const_key(resp_cmnd_failed, -1), be_const_func(l_respCmndFailed) }, + { be_const_key(remove_rule, 0), be_const_closure(remove_rule_closure) }, + { be_const_key(web_send, 9), be_const_func(l_webSend) }, + { be_const_key(resp_cmnd, -1), be_const_func(l_respCmnd) }, + { be_const_key(remove_timer, 10), be_const_closure(remove_timer_closure) }, { be_const_key(memory, -1), be_const_func(l_memory) }, { be_const_key(cb_dispatch, -1), be_const_closure(cb_dispatch_closure) }, - { be_const_key(remove_rule, 36), be_const_closure(remove_rule_closure) }, + { be_const_key(wire2, -1), be_const_var(4) }, + { be_const_key(find_op, -1), be_const_closure(find_op_closure) }, { be_const_key(resolvecmnd, -1), be_const_func(l_resolveCmnd) }, - { be_const_key(wifi, -1), be_const_func(l_wifi) }, - { be_const_key(exec_cmd, -1), be_const_closure(exec_cmd_closure) }, - { be_const_key(settings, 60), be_const_var(9) }, - { be_const_key(_global_def, -1), be_const_comptr(&be_tasmota_global_struct) }, - { be_const_key(resp_cmnd_failed, -1), be_const_func(l_respCmndFailed) }, + { be_const_key(get_option, -1), be_const_func(l_getoption) }, + { be_const_key(kv, 65), be_const_closure(kv_closure) }, + { be_const_key(wire_scan, -1), be_const_closure(wire_scan_closure) }, + { be_const_key(get_light, -1), be_const_closure(get_light_closure) }, + { be_const_key(_cmd, -1), be_const_func(l_cmd) }, { be_const_key(gc, -1), be_const_closure(gc_closure) }, - { be_const_key(yield, -1), be_const_func(l_yield) }, - { be_const_key(_drivers, -1), be_const_var(10) }, + { be_const_key(get_power, -1), be_const_func(l_getpower) }, + { be_const_key(cmd, 60), be_const_closure(cmd_closure) }, + { be_const_key(time_dump, -1), be_const_func(l_time_dump) }, + { be_const_key(settings, -1), be_const_var(5) }, + { be_const_key(load, -1), be_const_closure(load_closure) }, + { be_const_key(arch, -1), be_const_func(l_arch) }, + { be_const_key(_ccmd, -1), be_const_var(6) }, + { be_const_key(_get_cb, -1), be_const_func(l_get_cb) }, + { be_const_key(find_key_i, 19), be_const_closure(find_key_i_closure) }, + { be_const_key(time_reached, -1), be_const_func(l_timereached) }, + { be_const_key(run_deferred, -1), be_const_closure(run_deferred_closure) }, + { be_const_key(_settings_def, -1), be_const_comptr(&be_tasmota_settings_struct) }, + { be_const_key(save, 25), be_const_func(l_save) }, { be_const_key(millis, -1), be_const_func(l_millis) }, - { be_const_key(kv, -1), be_const_closure(kv_closure) }, + { be_const_key(web_send_decimal, -1), be_const_func(l_webSendDecimal) }, + { be_const_key(wire1, 72), be_const_var(7) }, + { be_const_key(delay, -1), be_const_func(l_delay) }, + { be_const_key(scale_uint, 50), be_const_func(l_scaleuint) }, + { be_const_key(get_switch, -1), be_const_func(l_getswitch) }, + { be_const_key(wifi, 38), be_const_func(l_wifi) }, + { be_const_key(publish_result, -1), be_const_func(l_publish_result) }, + { be_const_key(_drivers, -1), be_const_var(8) }, + { be_const_key(add_cmd, -1), be_const_closure(add_cmd_closure) }, + { be_const_key(strftime, -1), be_const_func(l_strftime) }, + { be_const_key(log, -1), be_const_func(l_logInfo) }, + { be_const_key(add_rule, -1), be_const_closure(add_rule_closure) }, + { be_const_key(resp_cmnd_done, 74), be_const_func(l_respCmndDone) }, + { be_const_key(_rules, 16), be_const_var(9) }, + { be_const_key(remove_cmd, -1), be_const_closure(remove_cmd_closure) }, + { be_const_key(init, -1), be_const_closure(init_closure) }, + { be_const_key(wd, 52), be_const_var(10) }, }; static be_define_const_map( be_class_tasmota_map, - 76 + 77 ); BE_EXPORT_VARIABLE be_define_const_class( diff --git a/lib/libesp32/Berry/src/be_solidifylib.c b/lib/libesp32/Berry/src/be_solidifylib.c index 1562c3bb6..c91bc22a5 100644 --- a/lib/libesp32/Berry/src/be_solidifylib.c +++ b/lib/libesp32/Berry/src/be_solidifylib.c @@ -127,7 +127,9 @@ static void m_solidify_bvalue(bvm *vm, bvalue * value, const char *classname, co } break; case BE_CLOSURE: - logfmt("be_const_closure(%s_closure)", str(((bclosure*) var_toobj(value))->proto->name)); + logfmt("be_const_closure(%s%s%s_closure)", + classname ? classname : "", classname ? "_" : "", + str(((bclosure*) var_toobj(value))->proto->name)); break; case BE_CLASS: logfmt("be_const_class(be_class_%s)", str(((bclass*) var_toobj(value))->name)); @@ -271,7 +273,7 @@ static void m_solidify_proto(bvm *vm, bproto *pr, const char * func_name, int bu } -static void m_solidify_closure(bvm *vm, bclosure *cl, int builtins) +static void m_solidify_closure(bvm *vm, bclosure *cl, const char * classname, int builtins) { bproto *pr = cl->proto; const char * func_name = str(pr->name); @@ -289,7 +291,9 @@ static void m_solidify_closure(bvm *vm, bclosure *cl, int builtins) logfmt("** Solidified function: %s\n", func_name); logfmt("********************************************************************/\n"); - logfmt("be_local_closure(%s, /* name */\n", func_name); + logfmt("be_local_closure(%s%s%s, /* name */\n", + classname ? classname : "", classname ? "_" : "", + func_name); m_solidify_proto(vm, pr, func_name, builtins, indent); logfmt("\n"); @@ -310,7 +314,7 @@ static void m_solidify_subclass(bvm *vm, bclass *cl, int builtins) while ((node = be_map_next(cl->members, &iter)) != NULL) { if (var_isstr(&node->key) && var_isclosure(&node->value)) { bclosure *f = var_toobj(&node->value); - m_solidify_closure(vm, f, builtins); + m_solidify_closure(vm, f, class_name, builtins); } } } @@ -364,14 +368,18 @@ static void m_solidify_module(bvm *vm, bmodule *ml, int builtins) const char * module_name = be_module_name(ml); if (!module_name) { module_name = ""; } - /* iterate on members to dump closures */ + /* iterate on members to dump closures and classes */ if (ml->table) { bmapnode *node; bmapiter iter = be_map_iter(); while ((node = be_map_next(ml->table, &iter)) != NULL) { if (var_isstr(&node->key) && var_isclosure(&node->value)) { bclosure *f = var_toobj(&node->value); - m_solidify_closure(vm, f, builtins); + m_solidify_closure(vm, f, NULL, builtins); + } + if (var_isstr(&node->key) && var_isclass(&node->value)) { + bclass *cl = var_toobj(&node->value); + m_solidify_subclass(vm, cl, builtins); } } } @@ -405,7 +413,7 @@ static int m_dump(bvm *vm) if (be_top(vm) >= 1) { bvalue *v = be_indexof(vm, 1); if (var_isclosure(v)) { - m_solidify_closure(vm, var_toobj(v), be_builtin_count(vm)); + m_solidify_closure(vm, var_toobj(v), NULL, be_builtin_count(vm)); } else if (var_isclass(v)) { m_solidify_class(vm, var_toobj(v), be_builtin_count(vm)); } else if (var_ismodule(v)) { diff --git a/tasmota/berry/leds/rainbow.be b/tasmota/berry/leds/rainbow.be index eebd485a3..03dcd1a86 100644 --- a/tasmota/berry/leds/rainbow.be +++ b/tasmota/berry/leds/rainbow.be @@ -9,6 +9,8 @@ rainbow.start() -# +import animate + # https://stackoverflow.com/questions/34187171/fast-integer-square-root-approximation def fast_sqrt_int(val) var a, b @@ -42,13 +44,14 @@ class Rainbow : Leds_animator 0xEE82EE, #- violet -# ] - def init(strip) + def init(strip, duration) super(self).init(strip) self.cur_offset = 0 + # add an animator to change `self.cur_offset` to each value of the palette + self.add_anim(animate.rotate(def(v) self.cur_offset = v end, 0, size(self.palette), int(duration * 1000))) end def animate() - var i = 0 # move instance variables to registers to avoid GETMBR inside the loop var cur_offset = self.cur_offset var modulus = size(self.palette) @@ -57,18 +60,25 @@ class Rainbow : Leds_animator var bri = self.bri var set_pixel_color = strip.set_pixel_color + var i = 0 while i < self.pixel_count # doing a loop rather than a `for` prevents from allocating a new object var col = palette[(cur_offset + i) % modulus] set_pixel_color(strip, i, col, bri) # simulate the method call without GETMET i += 1 end strip.show() - # advance to next color - self.cur_offset = (self.cur_offset + 1) % modulus end end +#- + +var strip = Leds_matrix(5,5, gpio.pin(gpio.WS2812, 1)) +var r = Rainbow(strip, 1.0) +r.start() + +-# + class Rainbow_Matrix : Leds_animator var cur_offset # current offset in the palette static palette = [ 0xFF0000, #- red -# @@ -80,9 +90,11 @@ class Rainbow_Matrix : Leds_animator 0xEE82EE, #- violet -# ] - def init(strip) + def init(strip, duration) super(self).init(strip) self.cur_offset = 0 + # add an animator to change `self.cur_offset` to each value of the palette + self.add_anim(animate.rotate(def(v) self.cur_offset = v end, 0, size(self.palette), int(duration * 1000))) end def animate() @@ -107,24 +119,31 @@ class Rainbow_Matrix : Leds_animator y += 1 end strip.show() - # advance to next color - self.cur_offset = (self.cur_offset + 1) % modulus end end +#- + +var strip = Leds_matrix(5,5, gpio.pin(gpio.WS2812, 1)) +var r = Rainbow_Matrix(strip, 0.5) +r.start() + +-# class Round : Leds_animator var cur_val var min_val, max_val var incr_val + var h - def init(strip) + def init(strip, glow_duration, color_duration) super(self).init(strip) self.cur_val = 5 << 8 - self.min_val = 2 << 8 - self.max_val = 6 << 8 - self.incr_val = 50 + self.h = 0 # start with hue = 0 (red) + # add animator for color over 30 colors + self.add_anim(animate.rotate(def(h) self.h = h end, 0, 359, int(color_duration * 1000))) + self.add_anim(animate.back_forth(def(v) self.cur_val = v end, 2 << 8, 6 << 8, int(glow_duration * 1000))) end def animate() @@ -136,12 +155,13 @@ class Round : Leds_animator var w = self.strip.w var ch = h / 2 var cw = w / 2 + var col_ref = tasmota.hs2rgb(self.h) var y = 0 while y < h var x = 0 while x < w - var col = 0xFF0000 # red + var col = col_ref var dist = fast_sqrt_int( ((y - ch)*(y - ch) + (x - cw)*(x - cw)) << 16) var rel_bri = tasmota.scale_uint(dist, 0, self.cur_val, bri, 0) set_matrix_pixel_color(strip, x, y, col, rel_bri) # simulate the method call without GETMET @@ -150,10 +170,14 @@ class Round : Leds_animator y += 1 end strip.show() - # - self.cur_val += self.incr_val - if self.cur_val > self.max_val self.cur_val = self.max_val self.incr_val = -self.incr_val end - if self.cur_val < self.min_val self.cur_val = self.min_val self.incr_val = -self.incr_val end end end + +#- + +var strip = Leds_matrix(5,5, gpio.pin(gpio.WS2812, 1)) +var r = Round(strip, 2, 30) +r.start() + +-# \ No newline at end of file From cbab510997eb37888a1a0bbb641b237c73f7b6d3 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Fri, 19 Nov 2021 22:29:20 +0100 Subject: [PATCH 062/185] Berry disable debug features --- lib/libesp32/Berry/default/berry_conf.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/libesp32/Berry/default/berry_conf.h b/lib/libesp32/Berry/default/berry_conf.h index e11d6c3cb..597c3d65b 100644 --- a/lib/libesp32/Berry/default/berry_conf.h +++ b/lib/libesp32/Berry/default/berry_conf.h @@ -194,12 +194,19 @@ #define BE_USE_OS_MODULE 0 #define BE_USE_GLOBAL_MODULE 1 #define BE_USE_SYS_MODULE 0 -#define BE_USE_DEBUG_MODULE 1 +#define BE_USE_DEBUG_MODULE 0 #define BE_USE_GC_MODULE 1 -#define BE_USE_SOLIDIFY_MODULE 1 +#define BE_USE_SOLIDIFY_MODULE 0 #define BE_USE_INTROSPECT_MODULE 1 #define BE_USE_STRICT_MODULE 1 +#ifdef USE_BERRY_DEBUG + #undef BE_USE_DEBUG_MODULE + #undef BE_USE_SOLIDIFY_MODULE + #define BE_USE_DEBUG_MODULE 1 + #define BE_USE_SOLIDIFY_MODULE 1 +#endif // USE_BERRY_DEBUG + /* Macro: BE_EXPLICIT_XXX * If these macros are defined, the corresponding function will * use the version defined by these macros. These macro definitions From ae7104a9d091df81889a198e2bb3af38a4ce334c Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Fri, 19 Nov 2021 22:53:16 +0100 Subject: [PATCH 063/185] Fix issue with module debug missing --- lib/libesp32/Berry/default/be_tasmotalib.c | 208 +++++++++--------- .../Berry/default/embedded/Tasmota.be | 2 +- 2 files changed, 105 insertions(+), 105 deletions(-) diff --git a/lib/libesp32/Berry/default/be_tasmotalib.c b/lib/libesp32/Berry/default/be_tasmotalib.c index dc07a8562..989b34752 100644 --- a/lib/libesp32/Berry/default/be_tasmotalib.c +++ b/lib/libesp32/Berry/default/be_tasmotalib.c @@ -1638,7 +1638,7 @@ be_local_closure(gc, /* name */ ********************************************************************/ be_local_closure(event, /* name */ be_nested_proto( - 21, /* nstack */ + 20, /* nstack */ 6, /* argc */ 0, /* varg */ 0, /* has upvals */ @@ -1648,23 +1648,23 @@ be_local_closure(event, /* name */ 1, /* has constants */ ( &(const bvalue[23]) { /* constants */ /* K0 */ be_nested_string("introspect", 164638290, 10), - /* K1 */ be_nested_string("debug", 1483009432, 5), - /* K2 */ be_nested_string("string", 398550328, 6), - /* K3 */ be_nested_string("every_50ms", -1911083288, 10), - /* K4 */ be_nested_string("run_deferred", 371594696, 12), - /* K5 */ be_nested_string("cmd", -158181397, 3), - /* K6 */ be_nested_string("exec_cmd", 493567399, 8), - /* K7 */ be_nested_string("tele", -820509235, 4), - /* K8 */ be_nested_string("exec_tele", 1020751601, 9), - /* K9 */ be_nested_string("rule", -64077613, 4), - /* K10 */ be_nested_string("exec_rules", 1445221092, 10), - /* K11 */ be_nested_string("gc", 1042313471, 2), - /* K12 */ be_nested_string("_drivers", -1034638311, 8), - /* K13 */ be_const_int(0), - /* K14 */ be_nested_string("get", 1410115415, 3), - /* K15 */ be_nested_string("function", -1630125495, 8), - /* K16 */ be_nested_string("format", -1180859054, 6), - /* K17 */ be_nested_string("BRY: Exception> '%s' - %s", -2047976332, 25), + /* K1 */ be_nested_string("string", 398550328, 6), + /* K2 */ be_nested_string("every_50ms", -1911083288, 10), + /* K3 */ be_nested_string("run_deferred", 371594696, 12), + /* K4 */ be_nested_string("cmd", -158181397, 3), + /* K5 */ be_nested_string("exec_cmd", 493567399, 8), + /* K6 */ be_nested_string("tele", -820509235, 4), + /* K7 */ be_nested_string("exec_tele", 1020751601, 9), + /* K8 */ be_nested_string("rule", -64077613, 4), + /* K9 */ be_nested_string("exec_rules", 1445221092, 10), + /* K10 */ be_nested_string("gc", 1042313471, 2), + /* K11 */ be_nested_string("_drivers", -1034638311, 8), + /* K12 */ be_const_int(0), + /* K13 */ be_nested_string("get", 1410115415, 3), + /* K14 */ be_nested_string("function", -1630125495, 8), + /* K15 */ be_nested_string("format", -1180859054, 6), + /* K16 */ be_nested_string("BRY: Exception> '%s' - %s", -2047976332, 25), + /* K17 */ be_nested_string("debug", 1483009432, 5), /* K18 */ be_nested_string("traceback", -909779187, 9), /* K19 */ be_const_int(1), /* K20 */ be_nested_string("save_before_restart", 1253239338, 19), @@ -1672,99 +1672,99 @@ be_local_closure(event, /* name */ /* K22 */ be_nested_string("save", -855671224, 4), }), (be_nested_const_str("event", -30355297, 5)), - (be_nested_const_str("tasmota.be", 1128870755, 10)), + ((bstring*) &be_const_str_input), ( &(const binstruction[91]) { /* code */ 0xA41A0000, // 0000 IMPORT R6 K0 0xA41E0200, // 0001 IMPORT R7 K1 - 0xA4220400, // 0002 IMPORT R8 K2 - 0x1C240303, // 0003 EQ R9 R1 K3 - 0x78260001, // 0004 JMPF R9 #0007 - 0x8C240104, // 0005 GETMET R9 R0 K4 - 0x7C240200, // 0006 CALL R9 1 - 0x50240000, // 0007 LDBOOL R9 0 0 - 0x1C280305, // 0008 EQ R10 R1 K5 - 0x782A0006, // 0009 JMPF R10 #0011 - 0x8C280106, // 000A GETMET R10 R0 K6 - 0x5C300400, // 000B MOVE R12 R2 - 0x5C340600, // 000C MOVE R13 R3 - 0x5C380800, // 000D MOVE R14 R4 - 0x7C280800, // 000E CALL R10 4 - 0x80041400, // 000F RET 1 R10 - 0x70020043, // 0010 JMP #0055 - 0x1C280307, // 0011 EQ R10 R1 K7 - 0x782A0004, // 0012 JMPF R10 #0018 - 0x8C280108, // 0013 GETMET R10 R0 K8 - 0x5C300800, // 0014 MOVE R12 R4 - 0x7C280400, // 0015 CALL R10 2 - 0x80041400, // 0016 RET 1 R10 - 0x7002003C, // 0017 JMP #0055 - 0x1C280309, // 0018 EQ R10 R1 K9 - 0x782A0004, // 0019 JMPF R10 #001F - 0x8C28010A, // 001A GETMET R10 R0 K10 - 0x5C300800, // 001B MOVE R12 R4 - 0x7C280400, // 001C CALL R10 2 - 0x80041400, // 001D RET 1 R10 - 0x70020035, // 001E JMP #0055 - 0x1C28030B, // 001F EQ R10 R1 K11 - 0x782A0003, // 0020 JMPF R10 #0025 - 0x8C28010B, // 0021 GETMET R10 R0 K11 - 0x7C280200, // 0022 CALL R10 1 - 0x80041400, // 0023 RET 1 R10 - 0x7002002F, // 0024 JMP #0055 - 0x8828010C, // 0025 GETMBR R10 R0 K12 - 0x782A002D, // 0026 JMPF R10 #0055 - 0x5828000D, // 0027 LDCONST R10 K13 - 0x602C000C, // 0028 GETGBL R11 G12 - 0x8830010C, // 0029 GETMBR R12 R0 K12 - 0x7C2C0200, // 002A CALL R11 1 - 0x142C140B, // 002B LT R11 R10 R11 - 0x782E0027, // 002C JMPF R11 #0055 - 0x882C010C, // 002D GETMBR R11 R0 K12 - 0x942C160A, // 002E GETIDX R11 R11 R10 - 0x8C300D0E, // 002F GETMET R12 R6 K14 - 0x5C381600, // 0030 MOVE R14 R11 - 0x5C3C0200, // 0031 MOVE R15 R1 - 0x7C300600, // 0032 CALL R12 3 - 0x60340004, // 0033 GETGBL R13 G4 - 0x5C381800, // 0034 MOVE R14 R12 - 0x7C340200, // 0035 CALL R13 1 - 0x1C341B0F, // 0036 EQ R13 R13 K15 - 0x7836001A, // 0037 JMPF R13 #0053 - 0xA802000C, // 0038 EXBLK 0 #0046 - 0x5C341800, // 0039 MOVE R13 R12 - 0x5C381600, // 003A MOVE R14 R11 - 0x5C3C0400, // 003B MOVE R15 R2 - 0x5C400600, // 003C MOVE R16 R3 - 0x5C440800, // 003D MOVE R17 R4 - 0x5C480A00, // 003E MOVE R18 R5 - 0x7C340A00, // 003F CALL R13 5 - 0x5C241A00, // 0040 MOVE R9 R13 - 0x78260001, // 0041 JMPF R9 #0044 - 0xA8040001, // 0042 EXBLK 1 1 - 0x70020010, // 0043 JMP #0055 - 0xA8040001, // 0044 EXBLK 1 1 - 0x7002000C, // 0045 JMP #0053 - 0xAC340002, // 0046 CATCH R13 0 2 - 0x70020009, // 0047 JMP #0052 - 0x603C0001, // 0048 GETGBL R15 G1 - 0x8C401110, // 0049 GETMET R16 R8 K16 - 0x58480011, // 004A LDCONST R18 K17 + 0x1C200302, // 0002 EQ R8 R1 K2 + 0x78220001, // 0003 JMPF R8 #0006 + 0x8C200103, // 0004 GETMET R8 R0 K3 + 0x7C200200, // 0005 CALL R8 1 + 0x50200000, // 0006 LDBOOL R8 0 0 + 0x1C240304, // 0007 EQ R9 R1 K4 + 0x78260006, // 0008 JMPF R9 #0010 + 0x8C240105, // 0009 GETMET R9 R0 K5 + 0x5C2C0400, // 000A MOVE R11 R2 + 0x5C300600, // 000B MOVE R12 R3 + 0x5C340800, // 000C MOVE R13 R4 + 0x7C240800, // 000D CALL R9 4 + 0x80041200, // 000E RET 1 R9 + 0x70020044, // 000F JMP #0055 + 0x1C240306, // 0010 EQ R9 R1 K6 + 0x78260004, // 0011 JMPF R9 #0017 + 0x8C240107, // 0012 GETMET R9 R0 K7 + 0x5C2C0800, // 0013 MOVE R11 R4 + 0x7C240400, // 0014 CALL R9 2 + 0x80041200, // 0015 RET 1 R9 + 0x7002003D, // 0016 JMP #0055 + 0x1C240308, // 0017 EQ R9 R1 K8 + 0x78260004, // 0018 JMPF R9 #001E + 0x8C240109, // 0019 GETMET R9 R0 K9 + 0x5C2C0800, // 001A MOVE R11 R4 + 0x7C240400, // 001B CALL R9 2 + 0x80041200, // 001C RET 1 R9 + 0x70020036, // 001D JMP #0055 + 0x1C24030A, // 001E EQ R9 R1 K10 + 0x78260003, // 001F JMPF R9 #0024 + 0x8C24010A, // 0020 GETMET R9 R0 K10 + 0x7C240200, // 0021 CALL R9 1 + 0x80041200, // 0022 RET 1 R9 + 0x70020030, // 0023 JMP #0055 + 0x8824010B, // 0024 GETMBR R9 R0 K11 + 0x7826002E, // 0025 JMPF R9 #0055 + 0x5824000C, // 0026 LDCONST R9 K12 + 0x6028000C, // 0027 GETGBL R10 G12 + 0x882C010B, // 0028 GETMBR R11 R0 K11 + 0x7C280200, // 0029 CALL R10 1 + 0x1428120A, // 002A LT R10 R9 R10 + 0x782A0028, // 002B JMPF R10 #0055 + 0x8828010B, // 002C GETMBR R10 R0 K11 + 0x94281409, // 002D GETIDX R10 R10 R9 + 0x8C2C0D0D, // 002E GETMET R11 R6 K13 + 0x5C341400, // 002F MOVE R13 R10 + 0x5C380200, // 0030 MOVE R14 R1 + 0x7C2C0600, // 0031 CALL R11 3 + 0x60300004, // 0032 GETGBL R12 G4 + 0x5C341600, // 0033 MOVE R13 R11 + 0x7C300200, // 0034 CALL R12 1 + 0x1C30190E, // 0035 EQ R12 R12 K14 + 0x7832001B, // 0036 JMPF R12 #0053 + 0xA802000C, // 0037 EXBLK 0 #0045 + 0x5C301600, // 0038 MOVE R12 R11 + 0x5C341400, // 0039 MOVE R13 R10 + 0x5C380400, // 003A MOVE R14 R2 + 0x5C3C0600, // 003B MOVE R15 R3 + 0x5C400800, // 003C MOVE R16 R4 + 0x5C440A00, // 003D MOVE R17 R5 + 0x7C300A00, // 003E CALL R12 5 + 0x5C201800, // 003F MOVE R8 R12 + 0x78220001, // 0040 JMPF R8 #0043 + 0xA8040001, // 0041 EXBLK 1 1 + 0x70020011, // 0042 JMP #0055 + 0xA8040001, // 0043 EXBLK 1 1 + 0x7002000D, // 0044 JMP #0053 + 0xAC300002, // 0045 CATCH R12 0 2 + 0x7002000A, // 0046 JMP #0052 + 0x60380001, // 0047 GETGBL R14 G1 + 0x8C3C0F0F, // 0048 GETMET R15 R7 K15 + 0x58440010, // 0049 LDCONST R17 K16 + 0x5C481800, // 004A MOVE R18 R12 0x5C4C1A00, // 004B MOVE R19 R13 - 0x5C501C00, // 004C MOVE R20 R14 - 0x7C400800, // 004D CALL R16 4 - 0x7C3C0200, // 004E CALL R15 1 - 0x8C3C0F12, // 004F GETMET R15 R7 K18 + 0x7C3C0800, // 004C CALL R15 4 + 0x7C380200, // 004D CALL R14 1 + 0xA43A2200, // 004E IMPORT R14 K17 + 0x8C3C1D12, // 004F GETMET R15 R14 K18 0x7C3C0200, // 0050 CALL R15 1 0x70020000, // 0051 JMP #0053 0xB0080000, // 0052 RAISE 2 R0 R0 - 0x00281513, // 0053 ADD R10 R10 K19 - 0x7001FFD2, // 0054 JMP #0028 - 0x1C280314, // 0055 EQ R10 R1 K20 - 0x782A0002, // 0056 JMPF R10 #005A - 0xA42A2A00, // 0057 IMPORT R10 K21 - 0x8C2C1516, // 0058 GETMET R11 R10 K22 - 0x7C2C0200, // 0059 CALL R11 1 - 0x80041200, // 005A RET 1 R9 + 0x00241313, // 0053 ADD R9 R9 K19 + 0x7001FFD1, // 0054 JMP #0027 + 0x1C240314, // 0055 EQ R9 R1 K20 + 0x78260002, // 0056 JMPF R9 #005A + 0xA4262A00, // 0057 IMPORT R9 K21 + 0x8C281316, // 0058 GETMET R10 R9 K22 + 0x7C280200, // 0059 CALL R10 1 + 0x80041000, // 005A RET 1 R8 }) ) ); diff --git a/lib/libesp32/Berry/default/embedded/Tasmota.be b/lib/libesp32/Berry/default/embedded/Tasmota.be index e1d7ef10e..42d87ec66 100644 --- a/lib/libesp32/Berry/default/embedded/Tasmota.be +++ b/lib/libesp32/Berry/default/embedded/Tasmota.be @@ -396,7 +396,6 @@ class Tasmota def event(event_type, cmd, idx, payload, raw) import introspect - import debug import string if event_type=='every_50ms' self.run_deferred() end #- first run deferred events -# @@ -417,6 +416,7 @@ class Tasmota if done break end except .. as e,m print(string.format("BRY: Exception> '%s' - %s", e, m)) + import debug debug.traceback() end end From 0cbd6cff4a26240c86eede5589e60f781b047b87 Mon Sep 17 00:00:00 2001 From: "@cociweb" Date: Fri, 19 Nov 2021 23:58:47 +0100 Subject: [PATCH 064/185] IRremoteESP8266 library from v2.7.20 to v2.8.0 --- .../IRremoteESP8266/.gitattributes | 3 + .../IRremoteESP8266/.github/CONTRIBUTING.md | 2 +- .../IRremoteESP8266/.github/Contributors.md | 1 + .../.github/ISSUE_TEMPLATE/problem-report.md | 57 + .../IRremoteESP8266/.github/issue_template.md | 47 - .../.github/workflows/Build.yml | 37 + .../.github/workflows/Documentation.yml | 15 + .../.github/workflows/Lint.yml | 28 + .../.github/workflows/MetaChecks.yml | 54 + .../.github/workflows/UnitTests.yml | 23 + .../IRremoteESP8266/.gitignore | 2 +- .../IRremoteESP8266/.gitmodules | 4 - .../IRremoteESP8266/.travis.yml | 69 - .../IRremoteESP8266/IRremoteESP8266/README.md | 4 +- .../IRremoteESP8266/README_de.md | 4 +- .../IRremoteESP8266/README_fr.md | 4 +- .../IRremoteESP8266/ReleaseNotes.md | 68 + .../IRremoteESP8266/SECURITY.md | 3 + .../IRremoteESP8266/SupportedProtocols.md | 34 +- .../examples/IRMQTTServer/IRMQTTServer.h | 54 +- .../examples/IRMQTTServer/IRMQTTServer.ino | 397 +++--- .../examples/IRrecvDumpV2/platformio.ini | 6 + .../examples/IRrecvDumpV3/platformio.ini | 9 + .../IRremoteESP8266/keywords.txt | 275 +++- .../IRremoteESP8266/library.json | 2 +- .../IRremoteESP8266/library.properties | 2 +- .../IRremoteESP8266/src/IRac.cpp | 981 ++++++++------ .../IRremoteESP8266/src/IRac.h | 47 +- .../IRremoteESP8266/src/IRrecv.cpp | 48 +- .../IRremoteESP8266/src/IRrecv.h | 15 +- .../IRremoteESP8266/src/IRremoteESP8266.h | 36 +- .../IRremoteESP8266/src/IRsend.cpp | 21 +- .../IRremoteESP8266/src/IRsend.h | 33 + .../IRremoteESP8266/src/IRtext.cpp | 404 +++--- .../IRremoteESP8266/src/IRtext.h | 372 +++--- .../IRremoteESP8266/src/IRutils.cpp | 173 ++- .../IRremoteESP8266/src/IRutils.h | 10 +- .../IRremoteESP8266/src/ir_Airton.cpp | 70 + .../IRremoteESP8266/src/ir_Arris.cpp | 123 ++ .../IRremoteESP8266/src/ir_Coolix.cpp | 6 +- .../IRremoteESP8266/src/ir_Electra.cpp | 82 +- .../IRremoteESP8266/src/ir_Electra.h | 27 +- .../IRremoteESP8266/src/ir_Epson.cpp | 7 + .../IRremoteESP8266/src/ir_Goodweather.cpp | 8 +- .../IRremoteESP8266/src/ir_Gree.cpp | 175 +-- .../IRremoteESP8266/src/ir_Gree.h | 54 +- .../IRremoteESP8266/src/ir_Haier.cpp | 477 ++++--- .../IRremoteESP8266/src/ir_Haier.h | 174 ++- .../IRremoteESP8266/src/ir_LG.h | 2 + .../IRremoteESP8266/src/ir_Mirage.cpp | 783 +++++++++++- .../IRremoteESP8266/src/ir_Mirage.h | 277 ++++ .../IRremoteESP8266/src/ir_Mitsubishi.cpp | 6 +- .../IRremoteESP8266/src/ir_Rhoss.cpp | 364 ++++++ .../IRremoteESP8266/src/ir_Rhoss.h | 145 +++ .../IRremoteESP8266/src/ir_Samsung.cpp | 331 +++-- .../IRremoteESP8266/src/ir_Samsung.h | 173 ++- .../IRremoteESP8266/src/ir_Sharp.cpp | 138 +- .../IRremoteESP8266/src/ir_Sharp.h | 28 +- .../IRremoteESP8266/src/ir_Symphony.cpp | 9 + .../IRremoteESP8266/src/ir_Tcl.cpp | 153 ++- .../IRremoteESP8266/src/ir_Tcl.h | 98 +- .../IRremoteESP8266/src/ir_Transcold.cpp | 10 +- .../IRremoteESP8266/src/locale/defaults.h | 184 ++- .../IRremoteESP8266/src/locale/pt-BR.h | 12 +- .../IRremoteESP8266/src/locale/ru-RU.h | 152 +++ .../IRremoteESP8266/src/locale/sv-SE.h | 189 +++ .../IRremoteESP8266/test/IRac_test.cpp | 334 ++++- .../IRremoteESP8266/test/Makefile | 8 + .../IRremoteESP8266/test/ir_Airton_test.cpp | 62 + .../IRremoteESP8266/test/ir_Arris_test.cpp | 189 +++ .../IRremoteESP8266/test/ir_Electra_test.cpp | 91 +- .../IRremoteESP8266/test/ir_Gree_test.cpp | 63 +- .../IRremoteESP8266/test/ir_Haier_test.cpp | 1123 ++++++++++------- .../IRremoteESP8266/test/ir_Mirage_test.cpp | 479 ++++++- .../IRremoteESP8266/test/ir_Rhoss_test.cpp | 396 ++++++ .../IRremoteESP8266/test/ir_Samsung_test.cpp | 574 ++++++++- .../IRremoteESP8266/test/ir_Sharp_test.cpp | 155 ++- .../IRremoteESP8266/test/ir_Tcl_test.cpp | 231 +++- .../test/ir_Teknopoint_test.cpp | 10 +- .../IRremoteESP8266/tools/Makefile | 12 +- .../tools/auto_analyse_raw_data.py | 250 ++-- .../tools/generate_irtext_h.sh | 16 +- .../IRremoteESP8266/tools/mkkeywords | 13 +- .../tools/raw_to_pronto_code.py | 28 +- .../tools/scrape_supported_devices.py | 426 +++++++ lib/lib_basic/IRremoteESP8266/library.json | 4 +- 86 files changed, 9402 insertions(+), 2663 deletions(-) create mode 100644 lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.gitattributes create mode 100644 lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/ISSUE_TEMPLATE/problem-report.md delete mode 100644 lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/issue_template.md create mode 100644 lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/workflows/Build.yml create mode 100644 lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/workflows/Documentation.yml create mode 100644 lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/workflows/Lint.yml create mode 100644 lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/workflows/MetaChecks.yml create mode 100644 lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/workflows/UnitTests.yml delete mode 100644 lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.gitmodules delete mode 100644 lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.travis.yml create mode 100644 lib/lib_basic/IRremoteESP8266/IRremoteESP8266/SECURITY.md create mode 100644 lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Airton.cpp create mode 100644 lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Arris.cpp create mode 100644 lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Mirage.h create mode 100644 lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Rhoss.cpp create mode 100644 lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Rhoss.h create mode 100644 lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/locale/ru-RU.h create mode 100644 lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/locale/sv-SE.h create mode 100644 lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Airton_test.cpp create mode 100644 lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Arris_test.cpp create mode 100644 lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Rhoss_test.cpp create mode 100755 lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/scrape_supported_devices.py diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.gitattributes b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.gitattributes new file mode 100644 index 000000000..05945c4fb --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.gitattributes @@ -0,0 +1,3 @@ +# Directories & files to ignore from release archives +docs export-ignore +assets export-ignore diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/CONTRIBUTING.md b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/CONTRIBUTING.md index 20bb97d94..87fd34fc1 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/CONTRIBUTING.md +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/CONTRIBUTING.md @@ -71,7 +71,7 @@ Include details about your configuration, circuit and environment: * Avoid platform-dependent code. * Use c98 types where possible for better portablity. * In almost all cases, code & documentation should be peer-reviewed by at least one other contributor. -* The code should pass all the existing testing infrastructure in Travis. e.g. Unit tests, cpplint, and basic compilation. +* The code should pass all the existing testing infrastructure in GitHub Actions. e.g. Unit tests, cpplint, and basic compilation etc. * State if you have tested this under real conditions if you have, and what other tests you may have carried out. ### Git Commit Messages diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/Contributors.md b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/Contributors.md index 811bfea84..afa0a51e9 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/Contributors.md +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/Contributors.md @@ -18,6 +18,7 @@ - [Mark Kuchel](https://github.com/kuchel77) - [Christian Nilsson](https://github.com/NiKiZe) - [Zhongxian Li](https://github.com/siriuslzx) +- [Davide Depau](https://github.com/Depau) All contributors can be found on the [contributors site](https://github.com/crankyoldgit/IRremoteESP8266/graphs/contributors). diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/ISSUE_TEMPLATE/problem-report.md b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/ISSUE_TEMPLATE/problem-report.md new file mode 100644 index 000000000..1f1556781 --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/ISSUE_TEMPLATE/problem-report.md @@ -0,0 +1,57 @@ +--- +name: Problem report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +### Version/revision of the library used +_Typically located in the `library.json` & `src/IRremoteESP8266.h` files in the root directory of the library. +e.g. v2.0.0, or 'master' as at 1st of June, 2017. etc._ + +### Describe the bug +A clear and concise description of what the bug is. + +#### To Reproduce +_What steps did you do, and what did or didn't actually happen? How can we reproduce the issue?_ + +_e.g._ +_1. Initialise the IRsend class._ +_2. `IRsend.sendFoobar(0xdeadbeef);`_ +_3. Foobar BBQ went into Cow(er)-saving mode and fried me a couple of eggs instead._ + +#### Example code used +_Include all relevant code snippets or links to the actual code files. Tip: [How to quote your code so it is still readable in the report](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code)._ + +#### Expected behaviour +_What steps did you do and what should it have done? A clear and concise description of what you expected to happen._ + +_e.g._ +_1. Initialise the IRsend class._ +_2. `IRsend.sendFoobar(0xdeadbeef);`_ +_3. Foobar branded BBQ turns on and cooks me some ribs._ + +#### Output of raw data from [IRrecvDumpV2.ino](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/examples/IRrecvDumpV2/IRrecvDumpV2.ino) or [V3](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/examples/IRrecvDumpV3/) (if applicable) +_Include some serial text of the raw dumps of what the device saw._ + +_**Note**: Output from Tasmota is not acceptable. We can't easily use their raw format._ + + +### What brand/model IR demodulator are you using? +_Brand/Model code_ or _None_ + +_If VS1838b: That is likely your problem. Please buy a better one & try again. Reporting a capture or decode issue when you use one of these is effectively wasting our & your time. See the [FAQ](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Frequently-Asked-Questions#Help_Im_getting_very_inconsistent_results_when_capturing_an_IR_message_using_a_VS1838b_IR_demodulator)_ + +### Circuit diagram and hardware used (if applicable) +_Link to an image of the circuit diagram used. Part number of the IR receiver module etc. ESP8266 or ESP32 board type._ + +### I have followed the steps in the [Troubleshooting Guide](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Troubleshooting-Guide) & read the [FAQ](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Frequently-Asked-Questions) +_Yes/No._ + +### Has this library/code previously worked as expected for you? +_Yes/No. If "Yes", which version last worked for you?_ + +### Other useful information +_More information is always welcome. Be verbose._ diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/issue_template.md b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/issue_template.md deleted file mode 100644 index f0ecf1fba..000000000 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/issue_template.md +++ /dev/null @@ -1,47 +0,0 @@ -_(Please use this template for reporting issues. You can delete what ever is not relevant. Giving us this information will help us help you faster. Please also read the [FAQ](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Frequently-Asked-Questions) & [Troubleshooting Guide](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Troubleshooting-Guide). Your problem may already have an answer there.)_ - -### Version/revision of the library used -_Typically located in the `library.json` & `src/IRremoteESP8266.h` files in the root directory of the library. -e.g. v2.0.0, or 'master' as at 1st of June, 2017. etc._ - -### Expected behavior -_What steps did you do and what should it have done?_ - -e.g. -1. Initialise the IRsend class. -2. IRsend.sendFoobar(0xdeadbeef); -3. Foobar branded BBQ turns on and cooks me some ribs. - -### Actual behavior -_What steps did you do, and what did or didn't actually happen?_ - -e.g. -1. Initialise the IRsend class. -2. IRsend.sendFoobar(0xdeadbeef); -3. Foobar BBQ went into Cow(er)-saving mode and fried me a couple of eggs instead. - -#### Output of raw data from IRrecvDumpV2.ino (if applicable) -_Include some raw dumps of what the device saw._ - -### What brand/model IR demodulator are you using? -_Brand/Model code_ or _None_ - -_If VS1838b: That is likely your problem. Please buy a better one & try again. Reporting a capture or decode issue when you use one of these is effectively wasting our & your time. See the [FAQ](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Frequently-Asked-Questions#Help_Im_getting_very_inconsistent_results_when_capturing_an_IR_message_using_a_VS1838b_IR_demodulator)_ - -### Steps to reproduce the behavior -_What can we do to (pref. reliably) repeat what is happening?_ - -#### Example code used -_Include all relevant code snippets or links to the actual code files. Tip: [How to quote your code so it is still readable](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code)._ - -#### Circuit diagram and hardware used (if applicable) -_Link to an image of the circuit diagram used. Part number of the IR receiver module etc. ESP8266 or ESP32 board type._ - -### I have followed the steps in the [Troubleshooting Guide](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Troubleshooting-Guide) & read the [FAQ](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Frequently-Asked-Questions) -_Yes/No._ - -### Has this library/code previously worked as expected for you? -_Yes/No. If "Yes", which version last worked for you?_ - -### Other useful information -_More information is always welcome. Be verbose._ diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/workflows/Build.yml b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/workflows/Build.yml new file mode 100644 index 000000000..5c0e5907c --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/workflows/Build.yml @@ -0,0 +1,37 @@ +name: Build + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + Build_Examples: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Cache pip + uses: actions/cache@v2 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip- + - name: Cache PlatformIO + uses: actions/cache@v2 + with: + path: ~/.platformio + key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }} + - name: Set up Python + uses: actions/setup-python@v2 + - name: Install PlatformIO + run: | + python -m pip install --upgrade pip + pip install --upgrade platformio + - name: Build all the examples + env: + PLATFORMIO_BUILD_CACHE_DIR: "../../.pio/buildcache" + run: find . -name platformio.ini -type f | sed 's,/platformio.ini$,,' | xargs --verbose -n 1 pio run --jobs 2 --project-dir diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/workflows/Documentation.yml b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/workflows/Documentation.yml new file mode 100644 index 000000000..e7520577c --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/workflows/Documentation.yml @@ -0,0 +1,15 @@ +# This is a basic workflow that is triggered on push/PRs to the master branch. + +name: Documentation + +# Controls when the action will run. Workflow runs when manually triggered using the UI +# or API. +on: [push, pull_request] + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + Doxygen: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: mattnotmitt/doxygen-action@v1 diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/workflows/Lint.yml b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/workflows/Lint.yml new file mode 100644 index 000000000..a0f7664d9 --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/workflows/Lint.yml @@ -0,0 +1,28 @@ +name: Code Lint + +on: [push, pull_request] + +jobs: + Linters: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up Python 3.9 + uses: actions/setup-python@v2 + with: + python-version: 3.9 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pylint + pip install cpplint + - name: Analysing the code with pylint + run: | + shopt -s nullglob + pylint -d F0001 {src,test,tools}/*.py + - name: Analysing the code with cpplint + run: | + shopt -s nullglob + cpplint --extensions=c,cc,cpp,ino --headers=h,hpp {src,src/locale,test,tools}/*.{h,c,cc,cpp,hpp,ino} examples/*/*.{h,c,cc,cpp,hpp,ino} diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/workflows/MetaChecks.yml b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/workflows/MetaChecks.yml new file mode 100644 index 000000000..2866ffc37 --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/workflows/MetaChecks.yml @@ -0,0 +1,54 @@ +# This is a basic workflow that is triggered on push/PRs to the master branch. + +name: Library Linter + +# Controls when the action will run. Workflow runs when manually triggered using the UI +# or API. +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + arduino-library-manager-lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: arduino/arduino-lint-action@v1 + with: + library-manager: update + compliance: strict + # Detect case-insensitive file duplication in the same directory. + # This can cause a problem for the Arduino IDE on Windows & Macs. + # See: + # - https://github.com/arduino/Arduino/issues/11441 + # - https://github.com/crankyoldgit/IRremoteESP8266/issues/1451 + detect-duplicate-files: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Look for case-insensitive filename collisions. + run: DUPS=$(find . -path '*/.pio' -prune -o -print | sort | uniq -D -i); if [[ -n "${DUPS}" ]]; then echo -e "Duplicates found:\n${DUPS}"; false; fi + version-number-consitent: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Check all the version numbers match. + run: | + LIB_VERSION=$(egrep "^#define\s+_IRREMOTEESP8266_VERSION_\s+" src/IRremoteESP8266.h | cut -d\" -f2) + test ${LIB_VERSION} == "$(jq -r .version library.json)" + grep -q "^version=${LIB_VERSION}$" library.properties + examples-have-platformio_ini: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Check that every example directory has a platformio.ini file. + run: (status=0; for dir in examples/*; do if [[ ! -f "${dir}/platformio.ini" ]]; then echo "${dir} has no 'platform.ini' file!"; status=1; fi; done; exit ${status}) + supported-devices-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Check that all files have supported sections. + run: (SUPPORTED_OUTPUT=$(python3 tools/scrape_supported_devices.py --noout --alert 2>&1); if [[ $? -ne 0 || -n "${SUPPORTED_OUTPUT}" ]]; then echo "${SUPPORTED_OUTPUT}"; exit 1; fi) diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/workflows/UnitTests.yml b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/workflows/UnitTests.yml new file mode 100644 index 000000000..bbc486b18 --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.github/workflows/UnitTests.yml @@ -0,0 +1,23 @@ +name: Tests + +on: [push, pull_request] + +jobs: + Unit_Tests: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Install the Google test suite + env: + MAKEFLAGS: "-j 2" + run: (cd test; make install-googletest) + - name: Build and run the library unit tests. + env: + MAKEFLAGS: "-j 2" + run: (cd test; make run) + - name: Build and run the tools unit tests. + env: + MAKEFLAGS: "-j 2" + run: (cd tools; make all; make run_tests) diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.gitignore b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.gitignore index c02171953..a73bc8b00 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.gitignore +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.gitignore @@ -22,7 +22,7 @@ examples/**/lib examples/**/.travis.yml examples/**/.gitignore lib/readme.txt -lib/googletest/**/* +lib/googletest/ # GCC pre-compiled headers. **/*.gch diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.gitmodules b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.gitmodules deleted file mode 100644 index c28fe0509..000000000 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.gitmodules +++ /dev/null @@ -1,4 +0,0 @@ -[submodule "lib/googletest"] - path = lib/googletest - url = https://github.com/google/googletest.git - branch = v1.8.x diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.travis.yml b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.travis.yml deleted file mode 100644 index 704004f68..000000000 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/.travis.yml +++ /dev/null @@ -1,69 +0,0 @@ -language: c -addons: - apt: - packages: - - jq - - doxygen - - graphviz - - python3 - - python3-pip - - pylint3 - - python3-setuptools -env: - - PLATFORMIO_BUILD_CACHE_DIR="../../.pio/buildcache" - IRRECVDUMP_RE=".*IRrecvDumpV.*" - IRMQTTSERVER_RE=".*IRMQTTServer.*" - MAKEFLAGS="-j 2" -cache: - directories: - - "~/.platformio" -before_install: - - wget https://raw.githubusercontent.com/google/styleguide/gh-pages/cpplint/cpplint.py - - python --version && pip --version - - python3 --version && pip3 --version - - sudo pip3 install -U platformio - - pio update -script: echo Running checks -notifications: - email: - on_success: change - on_failure: change -jobs: - include: - - name: "Compile the trivial examples" - script: - # Check that everything compiles but some heavy tasks e.g. IRMQTTServer & IRrecvDumpV2+ - # i.e. We are splitting the work load in to parallel tasks. - - find . -regextype egrep -name platformio.ini -type f \! -regex "${IRRECVDUMP_RE}|${IRMQTTSERVER_RE}" | sed 's,/platformio.ini$,,' | xargs --verbose -n 1 pio run --jobs 2 --project-dir - - name: "Compile the IRrecvDumpV2+ examples" - script: - # Check that IRrecvDumpV2+ compiles. - # i.e. We are splitting the work load in to parallel tasks. - - find . -regextype egrep -name platformio.ini -type f -regex "${IRRECVDUMP_RE}" | sed 's,/platformio.ini$,,' | xargs --verbose -n 1 pio run --jobs 2 --project-dir - - name: "Unit tests, Linter, Doc checks, & Compile IRMQTTServer" - script: - # Run all the Tests & check the code linters have no issues, and that - # IRMQTTServer compiles. - # i.e. We are splitting the work load in to parallel tasks. - # Check the version numbers match. - - LIB_VERSION=$(egrep "^#define\s+_IRREMOTEESP8266_VERSION_\s+" src/IRremoteESP8266.h | cut -d\" -f2) - - test ${LIB_VERSION} == "$(jq -r .version library.json)" - - grep -q "^version=${LIB_VERSION}$" library.properties - # Check the tools programs compile. - - (cd tools; make all) - # Check for lint issues. - - shopt -s nullglob - - python cpplint.py --extensions=c,cc,cpp,ino --headers=h,hpp {src,src/locale,test,tools}/*.{h,c,cc,cpp,hpp,ino} examples/*/*.{h,c,cc,cpp,hpp,ino} - - pylint3 -d F0001 {src,test,tools}/*.py - - shopt -u nullglob - # Build and run the unit tests. - - (cd test; make run) - - (cd tools; make run_tests) - # Check that every example directory has a platformio.ini file. - - (status=0; for dir in examples/*; do if [[ ! -f "${dir}/platformio.ini" ]]; then echo "${dir} has no 'platform.ini' file!"; status=1; fi; done; exit ${status}) - # Check that doxygen completes without errors or warnings. - - (DOXYGEN_OUTPUT=$(doxygen 2>&1); if [[ $? -ne 0 || -n "${DOXYGEN_OUTPUT}" ]]; then echo "${DOXYGEN_OUTPUT}"; exit 1; fi) - # Check that all files has supported sections. - - (SUPPORTED_OUTPUT=$(python3 tools/scrape_supported_devices.py --noout --alert 2>&1); if [[ $? -ne 0 || -n "${SUPPORTED_OUTPUT}" ]]; then echo "${SUPPORTED_OUTPUT}"; exit 1; fi) - # Check that IRMQTTServer compiles. - - find . -regextype egrep -name platformio.ini -type f -regex "${IRMQTTSERVER_RE}" | sed 's,/platformio.ini$,,' | xargs --verbose -n 1 pio run --jobs 2 --project-dir diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README.md b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README.md index 5dae9cfd9..90fd8d4c8 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README.md +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README.md @@ -10,8 +10,8 @@ This library enables you to **send _and_ receive** infra-red signals on an [ESP8266](https://github.com/esp8266/Arduino) or an [ESP32](https://github.com/espressif/arduino-esp32) using the [Arduino framework](https://www.arduino.cc/) using common 940nm IR LEDs and common IR receiver modules. e.g. TSOP{17,22,24,36,38,44,48}* demodulators etc. -## v2.7.20 Now Available -Version 2.7.20 of the library is now [available](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). You can view the [Release Notes](ReleaseNotes.md) for all the significant changes. +## v2.8.0 Now Available +Version 2.8.0 of the library is now [available](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). You can view the [Release Notes](ReleaseNotes.md) for all the significant changes. #### Upgrading from pre-v2.0 Usage of the library has been slightly changed in v2.0. You will need to change your usage to work with v2.0 and beyond. You can read more about the changes required on our [Upgrade to v2.0](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Upgrading-to-v2.0) page. diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README_de.md b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README_de.md index 51ded0420..4dbd835c4 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README_de.md +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README_de.md @@ -11,8 +11,8 @@ Diese Programmbibliothek ermöglicht das **Senden _und_ Empfangen** von Infrarotsignalen mit [ESP8266](https://github.com/esp8266/Arduino)- und [ESP32](https://github.com/espressif/arduino-esp32)-Mikrocontrollern mithilfe des [Arduino-Frameworks](https://www.arduino.cc/) und handelsüblichen 940nm Infrarot-LEDs undIR-Empfängermodulen, wie zum Beispiel TSOP{17,22,24,36,38,44,48}*-Demodulatoren. -## v2.7.20 jetzt verfügbar -Version 2.7.20 der Bibliothek ist nun [verfügbar](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). Die [Versionshinweise](ReleaseNotes.md) enthalten alle wichtigen Neuerungen. +## v2.8.0 jetzt verfügbar +Version 2.8.0 der Bibliothek ist nun [verfügbar](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). Die [Versionshinweise](ReleaseNotes.md) enthalten alle wichtigen Neuerungen. #### Hinweis für Nutzer von Versionen vor v2.0 Die Benutzung der Bibliothek hat sich mit Version 2.0 leicht geändert. Einige Anpassungen im aufrufenden Code werden nötig sein, um mit Version ab 2.0 korrekt zu funktionieren. Mehr zu den Anpassungen finden sich auf unserer [Upgrade to v2.0](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Upgrading-to-v2.0)-Seite. diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README_fr.md b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README_fr.md index fe314c459..d7033c093 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README_fr.md +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/README_fr.md @@ -10,8 +10,8 @@ Cette librairie vous permetra de **recevoir et d'envoyer des signaux** infrarouge sur le protocole [ESP8266](https://github.com/esp8266/Arduino) ou sur le protocole [ESP32](https://github.com/espressif/arduino-esp32) en utilisant le [Arduino framework](https://www.arduino.cc/) qui utilise la norme 940nm IR LEDs et le module basique de reception d'onde IR. Exemple : TSOP{17,22,24,36,38,44,48}* modules etc. -## v2.7.20 disponible -Version 2.7.20 de la libraire est maintenant [disponible](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). Vous pouvez voir le [Release Notes](ReleaseNotes.md) pour tous les changements importants. +## v2.8.0 disponible +Version 2.8.0 de la libraire est maintenant [disponible](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). Vous pouvez voir le [Release Notes](ReleaseNotes.md) pour tous les changements importants. #### mise à jour depuis pre-v2.0 L'utilisation de la librairie à un peu changer depuis la version in v2.0. Si vous voulez l'utiliser vous devrez changer votre utilisation aussi. Vous pouvez vous renseigner sur les précondition d'utilisation ici : [Upgrade to v2.0](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Upgrading-to-v2.0) page. diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/ReleaseNotes.md b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/ReleaseNotes.md index f5bc0f66a..0f41b562d 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/ReleaseNotes.md +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/ReleaseNotes.md @@ -1,5 +1,73 @@ # Release Notes +## _v2.8.0 (20211119)_ + +**[Bug Fixes]** +- Fix compilation issue when using old 8266 Arduino Frameworks. (#1639 #1640) +- Fix potential security issue with `scrape_supported_devices.py` (#1616 #1619) + +**[Features]** +- SAMSUNG_AC + - Change `clean` setting to a toggle. (#1676 #1677) + - Highest fan speed is available without Powerful setting. (#1675 #1678) + - Change `beep` setting to a toggle. (#1669 #1671) + - Fix Beep for AR12TXEAAWKNEU (#1668 #1669) + - Add support for Horizontal Swing & Econo (#1277 #1667) + - Add support for On, Off, & Sleep Timers (#1277 #1662) + - Fix power control. Clean-up code & bitmaps from Checksum changes. (#1277 #1648 #1650) +- HAIER_AC176/HAIER_AC_YRW02 + - Add support A/B unit setting (#1672) + - Add support degree Fahrenheit (#1659) + - Add support `Lock` function (#1652) + - Implement horizontal swing feature (#1641) + - Implement Quiet setting. (#1634 #1635) +- Basic support for Airton Protocol (#1670 #1681) +- HAIER_AC176: Add Turbo and Quiet settings (#1634) +- Gree: Add `SwingH` & `Econo` control. (#1587 #1653) +- MIRAGE + - Add experimental detailed support. (#1573 #1615) + - Experimental detailed support for KKG29A-C1 remote. (#1573 #1660) +- ELECTRA_AC: Add support for "IFeel" & Sensor settings. (#1644 #1645) +- Add Russian translation (#1649) +- Add Swedish translation (#1627) +- Reduce flash space used. (#1633) +- Strings finally in Flash! (#1493 #1614 #1623) +- Add support for Rhoss Idrowall MPCV 20-30-35-40 A/C protocol (#1630) +- Make `IRAc::opmodeToString()` output nicer for humans. (#1613) +- TCL112AC/TEKNOPOINT: Add support for `GZ055BE1` model (#1486 #1602) +- Support for Arris protocol. (#1598) +- SharpAc: Allow position control of SwingV (#1590 #1594) + +**[Misc]** +- HAIER_AC176/HAIER_AC_YRW02 + - Replace some magic numbers with constants (#1679) + - Small fix `Quiet` and `Turbo` test (#1674) + - Fix `IRHaierAC176::getTemp()` return value description (#1663) +- Security Policy creation and changes. (#1616 #1617 #1618 #1621 #1680) +- IRrecvDumpV2/3: Update PlatformIO envs for missing languages (#1661) +- IRMQTTServer + - Use the correct string for Fan mode in Home Assistant. (#1610 #1657) + - Move a lot of the strings/text to flash. (#1638) +- Minor code style improvements. (#1656) +- Update Supported Devices + - HAIER_AC176 (#1673) + - LG A/C (#1651 #1655) + - Symphony (#1603 #1605) + - Epson (#1574 #1601) + - GREE (#1587 #1588) + - SharpAc (#1590 #1591) +- Add extra tests for LG2 protocol (#1654) +- Fix parameter expansion in several macros. +- Move some strings to `IRtext.cpp` & `locale/default.h` (#1637) +- RHOSS: Move include and defines to their correct places (#1636) +- Make makefile only build required files when running `run-%` target (#1632) +- Update Portuguese translation (#1628) +- Add possibility to run specific test case (#1625) +- Change `googletest` library ignore (#1626) +- Re-work "Fan Only" strings & matching. (#1610) +- Address `C0209` pylint warnings. (#1608) + + ## _v2.7.20 (20210828)_ **[Bug Fixes]** diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/SECURITY.md b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/SECURITY.md new file mode 100644 index 000000000..c98300789 --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/SECURITY.md @@ -0,0 +1,3 @@ +# Security Policy + +You can find this library's Security Policy and contact procedure at https://crankyoldgit.github.io/IRremoteESP8266/SECURITY diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/SupportedProtocols.md b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/SupportedProtocols.md index 348a6d641..cf960a0eb 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/SupportedProtocols.md +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/SupportedProtocols.md @@ -1,14 +1,16 @@ + Last generated: Fri 19 Nov 2021 00:35:37 +0000 ---> # IR Protocols supported by this library | Protocol | Brand | Model | A/C Model | Detailed A/C Support | | --- | --- | --- | --- | --- | +| [Airton](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Airton.cpp) | **Airton** | RD1A1 remote
SMVH09B-2A2A3NH ref. 409730 A/C | | - | | [Airwell](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Airwell.cpp) | **[Airwell](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Airwell.h)** | DLS 21 DCI R410 AW A/C
RC04 remote
RC08W remote | | Yes | | [Aiwa](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Aiwa.cpp) | **Aiwa** | RC-T501 RCU | | - | | [Amcor](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Amcor.cpp) | **[Amcor](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Amcor.h)** | ADR-853H A/C
TAC-444 remote
TAC-495 remote | | Yes | | [Argo](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Argo.cpp) | **[Argo](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Argo.h)** | Ulisse 13 DCI Mobile Split A/C | | Yes | +| [Arris](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Arris.cpp) | **Arris** | 120A V1.0 A18 remote
VIP1113M Set-top box | | - | | [Bose](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Bose.cpp) | **Bose** | Bose TV Speaker | | - | | [Carrier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Carrier.cpp) | **[Carrier/Surrey](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Carrier.h)** | 42QG5A55970 remote
53NGK009/012 Inverter
619EGX0090E0 A/C
619EGX0120E0 A/C
619EGX0180E0 A/C
619EGX0220E0 A/C | | Yes | | [Coolix](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.cpp) | **[Airwell](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Coolix.h)** | RC08B remote | | Yes | @@ -26,11 +28,13 @@ | [Doshisha](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Doshisha.cpp) | **Doshisha** | CZ-S32D LED Light
CZ-S38D LED Light
CZ-S50D LED Light
RCZ01 remote | | - | | [Ecoclim](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Ecoclim.cpp) | **[EcoClim](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Ecoclim.h)** | HYSFR-P348 remote
ZC200DPO A/C | | Yes | | [Electra](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Electra.cpp) | **[AUX](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Electra.h)** | KFR-35GW/BpNFW=3 A/C
YKR-T/011 remote | | Yes | +| [Electra](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Electra.cpp) | **[Centek](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Electra.h)** | SCT-65Q09 A/C
YKR-P/002E remote | | Yes | | [Electra](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Electra.cpp) | **[Electra](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Electra.h)** | Classic INV 17 / AXW12DCS A/C
YKR-M/003E remote | | Yes | | [Electra](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Electra.cpp) | **[Frigidaire](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Electra.h)** | FGPC102AB1 A/C | | Yes | +| [Electra](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Electra.cpp) | **[Subtropic](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Electra.h)** | SUB-07HN1_18Y A/C
YKR-H/102E remote | | Yes | | [EliteScreens](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_EliteScreens.cpp) | **Elite Screens** | CineTension2 / CineTension3 series
Home2 / Home3 series
Spectrum series
VMAX Plus4 series
VMAX2 / VMAX2 Plus series
ZSP-IR-B / ZSP-IR-W remote | | - | | [EliteScreens](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_EliteScreens.cpp) | **Lumene Screens** | Embassy | | - | -| [Epson](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Epson.cpp) | **Epson** | EN-TW9100W Projector | | - | +| [Epson](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Epson.cpp) | **Epson** | EN-TW9100W Projector
EX3220 Projector
EX5220 Projector
EX5230 Projector
EX6220 Projector
EX7220 Projector
VS230 Projector
VS330 Projector | | - | | [Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.cpp) | **[Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.h)** | AGTV14LAC A/C (ARRAH2E)
AR-DB1 remote (ARDB1)
AR-DL10 remote (ARDB1)
AR-RAC1E remote (ARRAH2E)
AR-RAE1E remote (ARRAH2E)
AR-RAH1U remote (ARREB1E)
AR-RAH2E remote (ARRAH2E)
AR-REB1E remote (ARREB1E)
AR-REW4E remote (ARREW4E)
AR-RY4 remote (ARRY4)
AST9RSGCW A/C (ARDB1)
ASTB09LBC A/C (ARRY4)
ASU12RLF A/C (ARREB1E)
ASU30C1 A/C (ARDB1)
ASYG09KETA-B A/C (ARREW4E)
ASYG30LFCA A/C (ARRAH2E)
ASYG7LMCA A/C (ARREB1E) | ARDB1
ARJW2
ARRAH2E
ARREB1E
ARREW4E
ARRY4 | Yes | | [Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.cpp) | **[Fujitsu General](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.h)** | AOHG09LLC A/C (ARRAH2E)
AR-JW2 remote (ARJW2)
AR-RCE1E remote (ARRAH2E)
ASHG09LLCA A/C (ARRAH2E) | ARDB1
ARJW2
ARRAH2E
ARREB1E
ARREW4E
ARRY4 | Yes | | [GICable](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_GICable.cpp) | **G.I. Cable** | XRC-200 remote | | - | @@ -39,11 +43,13 @@ | [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Amana](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | PBC093G00CC A/C
YX1FF remote | YAW1F
YBOFB | Yes | | [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Cooper & Hunter](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | CH-S09FTXG A/C
YB1F2 remote | YAW1F
YBOFB | Yes | | [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[EKOKAI](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | A/C | YAW1F
YBOFB | Yes | -| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | YAA1FBF remote
YB1F2F remote | YAW1F
YBOFB | Yes | +| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | VIR09HP115V1AH A/C
VIR12HP230V1AH A/C
YAA1FBF remote
YAN1F1 remote
YB1F2F remote | YAW1F
YBOFB | Yes | | [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Green](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | YBOFB remote
YBOFB2 remote | YAW1F
YBOFB | Yes | | [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[RusClimate](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | EACS/I-09HAR_X/N3 A/C
YAW1F remote | YAW1F
YBOFB | Yes | | [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Ultimate](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | Heat Pump | YAW1F
YBOFB | Yes | -| [Haier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Haier.cpp) | **[Haier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Haier.h)** | HSU-09HMC203 A/C (HAIER_AC_YRW02)
HSU07-HEA03 remote (HAIER_AC)
YR-W02 remote (HAIER_AC_YRW02) | | Yes | +| [Gree](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.cpp) | **[Vailland](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Gree.h)** | VAI5-035WNI A/C
YACIFB remote | YAW1F
YBOFB | Yes | +| [Haier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Haier.cpp) | **[Daichi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Haier.h)** | D-H A/C (HAIER_AC176) | | Yes | +| [Haier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Haier.cpp) | **[Haier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Haier.h)** | HSU-09HMC203 A/C (HAIER_AC_YRW02)
HSU07-HEA03 remote (HAIER_AC)
V9014557 M47 8D remote (HAIER_AC176)
YR-W02 remote (HAIER_AC_YRW02) | | Yes | | [Haier](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Haier.cpp) | **[Mabe](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Haier.h)** | MMI18HDBWCA6MI8 A/C (HAIER_AC176)
V12843 HJ200223 remote (HAIER_AC176) | | Yes | | [Hitachi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Hitachi.cpp) | **[Hitachi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Hitachi.h)** | KAZE-312KSDP A/C (HITACHI_AC1)
LT0541-HTA remote (HITACHI_AC1)
PC-LH3B (HITACHI_AC3)
R-LT0541-HTA/Y.K.1.1-1 V2.3 remote (HITACHI_AC1)
RAR-8P2 remote (HITACHI_AC424)
RAS-22NK A/C (HITACHI_AC344)
RAS-35THA6 remote
RAS-AJ25H A/C (HITACHI_AC424)
RF11T1 remote (HITACHI_AC344)
Series VI A/C (Circa 2007) (HITACHI_AC1) | | Yes | | [Inax](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Inax.cpp) | **Lixil** | Inax DT-BA283 Toilet | | - | @@ -53,7 +59,7 @@ | [Kelvinator](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Kelvinator.cpp) | **[Kelvinator](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Kelvinator.h)** | KSV26CRC A/C
KSV26HRC A/C
KSV35CRC A/C
KSV35HRC A/C
KSV53HRC A/C
KSV62HRC A/C
KSV70CRC A/C
KSV70HRC A/C
KSV80HRC A/C
YALIF Remote | | Yes | | [Kelvinator](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Kelvinator.cpp) | **[Sharp](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Kelvinator.h)** | A5VEY A/C
YB1FA remote | | Yes | | [LG](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_LG.cpp) | **[General Electric](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_LG.h)** | 6711AR2853M A/C Remote (LG)
AG1BH09AW101 Split A/C (LG) | | Yes | -| [LG](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_LG.cpp) | **[LG](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_LG.h)** | 6711A20083V remote (LG)
A4UW30GFA2 A/C (LG2 - AKB74955603 & AKB73757604)
AKB73757604 remote (LG2 - AKB73757604)
AKB74395308 remote (LG2)
AKB74955603 remote (LG2 - AKB74955603)
AKB75215403 remote (LG2)
AMNW09GSJA0 A/C (LG2 - AKB74955603)
AMNW24GTPA1 A/C (LG2 - AKB73757604)
S4-W12JA3AA A/C (LG2) | | Yes | +| [LG](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_LG.cpp) | **[LG](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_LG.h)** | 6711A20083V remote (LG)
A4UW30GFA2 A/C (LG2 - AKB74955603 & AKB73757604)
AKB73315611 remote (LG2 - AKB74955603)
AKB73757604 remote (LG2 - AKB73757604)
AKB74395308 remote (LG2)
AKB74955603 remote (LG2 - AKB74955603)
AKB75215403 remote (LG2)
AMNW09GSJA0 A/C (LG2 - AKB74955603)
AMNW24GTPA1 A/C (LG2 - AKB73757604)
MS05SQ NW0 A/C (LG2 - AKB74955603)
S4-W12JA3AA A/C (LG2) | | Yes | | [Lasertag](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Lasertag.cpp) | **Lasertag** | Phaser emitters | | - | | [Lego](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Lego.cpp) | **LEGO Power Functions** | IR Receiver | | - | | [Lutron](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Lutron.cpp) | **Lutron** | MIR-ITFS remote
MIR-ITFS-F remote
MIR-ITFS-LF remote
SP-HT remote | | - | @@ -69,7 +75,9 @@ | [Midea](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.cpp) | **[Pioneer System](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.h)** | RG66B6(B)/BGEFU1 remote (MIDEA)
RUBO18GMFILCAD A/C (18K BTU) (MIDEA)
RYBO12GMFILCAD A/C (12K BTU) (MIDEA)
UB018GMFILCFHD A/C (12K BTU) (MIDEA)
WS012GMFI22HLD A/C (12K BTU) (MIDEA)
WS018GMFI22HLD A/C (12K BTU) (MIDEA) | | Yes | | [Midea](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.cpp) | **[Trotec](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Midea.h)** | RG57H(B)/BGE remote (MIDEA)
TROTEC PAC 3900 X (MIDEA) | | Yes | | [MilesTag2](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_MilesTag2.cpp) | **Milestag2** | Various | | - | -| [Mirage](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mirage.cpp) | **Mirage** | VLU series A/C | | - | +| [Mirage](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mirage.cpp) | **[Maxell](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mirage.h)** | KKG9A-C1 remote
MX-CH18CF A/C | KKG29AC1
KKG9AC1 | Yes | +| [Mirage](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mirage.cpp) | **[Mirage](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mirage.h)** | VLU series A/C | KKG29AC1
KKG9AC1 | Yes | +| [Mirage](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mirage.cpp) | **[Tronitechnik](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mirage.h)** | KKG29A-C1 remote
Reykir 9000 A/C | KKG29AC1
KKG9AC1 | Yes | | [Mitsubishi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mitsubishi.cpp) | **[Mitsubishi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mitsubishi.h)** | HC3000 Projector (MITSUBISHI2)
KM14A 0179213 remote
MS-GK24VA A/C
TV (MITSUBISHI) | | Yes | | [Mitsubishi](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mitsubishi.cpp) | **[Mitsubishi Electric](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Mitsubishi.h)** | 001CP T7WE10714 remote (MITSUBISHI136)
KPOA remote (MITSUBISHI112)
MLZ-RX5017AS A/C (MITSUBISHI_AC)
MSH-A24WV A/C (MITSUBISHI112)
MSZ-GV2519 A/C (MITSUBISHI_AC)
MSZ-SF25VE3 A/C (MITSUBISHI_AC)
MSZ-ZW4017S A/C (MITSUBISHI_AC)
MUH-A24WV A/C (MITSUBISHI112)
PEAD-RP71JAA Ducted A/C (MITSUBISHI136)
RH151/M21ED6426 remote (MITSUBISHI_AC)
SG153/M21EDF426 remote (MITSUBISHI_AC)
SG15D remote (MITSUBISHI_AC) | | Yes | | [MitsubishiHeavy](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_MitsubishiHeavy.cpp) | **[Mitsubishi Heavy Industries](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_MitsubishiHeavy.h)** | RKX502A001C remote (88 bit)
RLA502A700B remote (152 bit)
SRKxxZJ-S A/C (88 bit)
SRKxxZM-S A/C (152 bit)
SRKxxZMXA-S A/C (152 bit) | | Yes | @@ -87,18 +95,21 @@ | [Pronto](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Pronto.cpp) | **Pronto** | Pronto Hex | | - | | [RC5_RC6](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_RC5_RC6.cpp) | **Philips** | RC-5X (RC5X)
Standard RC-5 (RC5)
Standard RC-6 (RC6) | | - | | [RCMM](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_RCMM.cpp) | **Microsoft** | XBOX 360 | | - | -| [Samsung](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Samsung.cpp) | **[Samsung](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Samsung.h)** | AH59-02692E Soundbar remote (SAMSUNG36)
AK59-00167A Bluray remote (SAMSUNG36)
AR09FSSDAWKNFA A/C (SAMSUNG_AC)
AR09HSFSBWKN A/C (SAMSUNG_AC)
AR12HSSDBWKNEU A/C (SAMSUNG_AC)
AR12KSFPEWQNET A/C (SAMSUNG_AC)
AR12NXCXAWKXEU A/C (SAMSUNG_AC)
BN59-01178B TV remote (SAMSUNG)
DB63-03556X003 remote
DB93-14195A remote (SAMSUNG_AC)
DB93-16761C remote
HW-J551 Soundbar (SAMSUNG36)
IEC-R03 remote
UA55H6300 TV (SAMSUNG) | | Yes | +| [Rhoss](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Rhoss.cpp) | **[Rhoss](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Rhoss.h)** | Idrowall MPCV 20-30-35-40 | | Yes | +| [Samsung](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Samsung.cpp) | **[Samsung](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Samsung.h)** | AH59-02692E Soundbar remote (SAMSUNG36)
AK59-00167A Bluray remote (SAMSUNG36)
AR09FSSDAWKNFA A/C (SAMSUNG_AC)
AR09HSFSBWKN A/C (SAMSUNG_AC)
AR12HSSDBWKNEU A/C (SAMSUNG_AC)
AR12KSFPEWQNET A/C (SAMSUNG_AC)
AR12NXCXAWKXEU A/C (SAMSUNG_AC)
AR12TXEAAWKNEU A/C (SAMSUNG_AC)
BN59-01178B TV remote (SAMSUNG)
DB63-03556X003 remote
DB93-14195A remote (SAMSUNG_AC)
DB93-16761C remote
DB96-24901C remote (SAMSUNG_AC)
HW-J551 Soundbar (SAMSUNG36)
IEC-R03 remote
UA55H6300 TV (SAMSUNG) | | Yes | | [Sanyo](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sanyo.cpp) | **[Sanyo](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sanyo.h)** | LC7461 transmitter IC (SANYO_LC7461)
RCS-2HS4E remote (SANYO_AC)
RCS-2S4E remote (SANYO_AC)
SA 8650B - disabled
SAP-K121AHA A/C (SANYO_AC)
SAP-K242AH A/C (SANYO_AC) | | Yes | -| [Sharp](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sharp.cpp) | **[Sharp](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sharp.h)** | AH-A12REVP-1 A/C (A903)
AH-AxSAY A/C (A907)
AH-PR13-GL A/C (A903)
AH-XP10NRY A/C (A903)
AY-ZP40KR A/C (A907)
CRMC-820 JBEZ remote (A903)
CRMC-A705 JBEZ remote (A705)
CRMC-A863 JBEZ remote (A903)
CRMC-A903JBEZ remote (A903)
CRMC-A907 JBEZ remote (A907)
LC-52D62U TV | A705
A903
A907 | Yes | +| [Sharp](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sharp.cpp) | **[Sharp](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sharp.h)** | AH-A12REVP-1 A/C (A903)
AH-AxSAY A/C (A907)
AH-PR13-GL A/C (A903)
AH-XP10NRY A/C (A903)
AY-ZP40KR A/C (A907)
CRMC-820 JBEZ remote (A903)
CRMC-A705 JBEZ remote (A705)
CRMC-A863 JBEZ remote (A903)
CRMC-A903JBEZ remote (A903)
CRMC-A907 JBEZ remote (A907)
CRMC-A950 JBEZ (A907)
LC-52D62U TV | A705
A903
A907 | Yes | | [Sherwood](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sherwood.cpp) | **Sherwood** | RC-138 remote
RD6505(B) Receiver | | - | | [Sony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sony.cpp) | **Sony** | HT-CT380 Soundbar (Uses 38kHz & 3 repeats) | | - | | [Symphony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Symphony.cpp) | **Blyss** | Owen-SW-5 3 Fan
WP-YK8 090218 remote | | - | | [Symphony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Symphony.cpp) | **SamHop** | SM3015 Fan Remote Control
SM5021 Encoder chip
SM5032 Decoder chip | | - | | [Symphony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Symphony.cpp) | **Satellite Electronic** | ID6 Remote
JY199I Fan driver
JY199I-L Fan driver | | - | +| [Symphony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Symphony.cpp) | **SilverCrest** | SSVS 85 A1 Fan | | - | | [Symphony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Symphony.cpp) | **Symphony** | Air Cooler 3Di | | - | | [Symphony](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Symphony.cpp) | **Westinghouse** | 78095 Remote
Ceiling fan | | - | -| [Tcl](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.cpp) | **[Leberg](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.h)** | LBS-TOR07 A/C | | Yes | -| [Tcl](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.cpp) | **[TCL](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.h)** | TAC-09CHSD/XA31I A/C | | Yes | +| [Tcl](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.cpp) | **[Leberg](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.h)** | LBS-TOR07 A/C (TAC09CHSD) | GZ055BE1
TAC09CHSD | Yes | +| [Tcl](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.cpp) | **[TCL](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.h)** | TAC-09CHSD/XA31I A/C (TAC09CHSD) | GZ055BE1
TAC09CHSD | Yes | +| [Tcl](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.cpp) | **[Teknopoint](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Tcl.h)** | Allegro SSA-09H A/C (GZ055BE1)
GZ-055B-E1 remote (GZ055BE1) | GZ055BE1
TAC09CHSD | Yes | | [Technibel](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Technibel.cpp) | **[Technibel](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Technibel.h)** | IRO PLUS | | Yes | | [Teco](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Teco.cpp) | **[Alaska](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Teco.h)** | SAC9010QC A/C
SAC9010QC remote | | Yes | | [Teknopoint](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Teknopoint.cpp) | **Teknopoint** | Allegro SSA-09H A/C
GZ-055B-E1 remote | | - | @@ -127,10 +138,12 @@ ## Send & decodable protocols: +- AIRTON - AIRWELL - AIWA_RC_T501 - AMCOR - ARGO +- ARRIS - BOSE - CARRIER_AC - CARRIER_AC40 @@ -202,6 +215,7 @@ - RC5X - RC6 - RCMM +- RHOSS - SAMSUNG - SAMSUNG36 - SAMSUNG_AC diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRMQTTServer/IRMQTTServer.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRMQTTServer/IRMQTTServer.h index 0563ac855..1d05d3691 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRMQTTServer/IRMQTTServer.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRMQTTServer/IRMQTTServer.h @@ -261,8 +261,8 @@ const uint16_t kMinUnknownSize = 2 * 10; #define KEY_RX_GPIO "rx" // Text for Last Will & Testament status messages. -const char* kLwtOnline = "Online"; -const char* kLwtOffline = "Offline"; +const char* const kLwtOnline = "Online"; +const char* const kLwtOffline = "Offline"; const uint8_t kHostnameLength = 30; const uint8_t kPortLength = 5; // Largest value of uint16_t is "65535". @@ -285,7 +285,7 @@ const uint16_t kJsonAcStateMaxSize = 1024; // Bytes // ----------------- End of User Configuration Section ------------------------- // Constants -#define _MY_VERSION_ "v1.5.2" +#define _MY_VERSION_ "v1.6.0" const uint8_t kRebootTime = 15; // Seconds const uint8_t kQuickDisplayTime = 2; // Seconds @@ -310,29 +310,29 @@ const int8_t kRxGpios[] = { // JSON stuff // Name of the json config file in SPIFFS. -const char* kConfigFile = "/config.json"; -const char* kMqttServerKey = "mqtt_server"; -const char* kMqttPortKey = "mqtt_port"; -const char* kMqttUserKey = "mqtt_user"; -const char* kMqttPassKey = "mqtt_pass"; -const char* kMqttPrefixKey = "mqtt_prefix"; -const char* kHostnameKey = "hostname"; -const char* kHttpUserKey = "http_user"; -const char* kHttpPassKey = "http_pass"; -const char* kCommandDelimiter = ","; +const char* const kConfigFile = "/config.json"; +const char* const kMqttServerKey = "mqtt_server"; +const char* const kMqttPortKey = "mqtt_port"; +const char* const kMqttUserKey = "mqtt_user"; +const char* const kMqttPassKey = "mqtt_pass"; +const char* const kMqttPrefixKey = "mqtt_prefix"; +const char* const kHostnameKey = "hostname"; +const char* const kHttpUserKey = "http_user"; +const char* const kHttpPassKey = "http_pass"; +const char* const kCommandDelimiter = ","; // URLs -const char* kUrlRoot = "/"; -const char* kUrlAdmin = "/admin"; -const char* kUrlAircon = "/aircon"; -const char* kUrlSendDiscovery = "/send_discovery"; -const char* kUrlExamples = "/examples"; -const char* kUrlGpio = "/gpio"; -const char* kUrlGpioSet = "/gpio/set"; -const char* kUrlInfo = "/info"; -const char* kUrlReboot = "/quitquitquit"; -const char* kUrlWipe = "/reset"; -const char* kUrlClearMqtt = "/clear_retained"; +const char* const kUrlRoot = "/"; +const char* const kUrlAdmin = "/admin"; +const char* const kUrlAircon = "/aircon"; +const char* const kUrlSendDiscovery = "/send_discovery"; +const char* const kUrlExamples = "/examples"; +const char* const kUrlGpio = "/gpio"; +const char* const kUrlGpioSet = "/gpio/set"; +const char* const kUrlInfo = "/info"; +const char* const kUrlReboot = "/quitquitquit"; +const char* const kUrlWipe = "/reset"; +const char* const kUrlClearMqtt = "/clear_retained"; #if MQTT_ENABLE const uint32_t kBroadcastPeriodMs = MQTTbroadcastInterval * 1000; // mSeconds. @@ -340,7 +340,7 @@ const uint32_t kBroadcastPeriodMs = MQTTbroadcastInterval * 1000; // mSeconds. // Default is 5 seconds per IR TX GPIOs (channels) used. const uint32_t kStatListenPeriodMs = 5 * 1000 * kNrOfIrTxGpios; // mSeconds const int32_t kMaxPauseMs = 10000; // 10 Seconds. -const char* kSequenceDelimiter = ";"; +const char* const kSequenceDelimiter = ";"; const char kPauseChar = 'P'; #if defined(ESP8266) const uint32_t kChipId = ESP.getChipId(); @@ -349,7 +349,7 @@ const uint32_t kChipId = ESP.getChipId(); const uint32_t kChipId = ESP.getEfuseMac(); // Discard the top 16 bits. #endif // ESP32 -const char* kClimateTopics = +static const char kClimateTopics[] PROGMEM = "(" KEY_PROTOCOL "|" KEY_MODEL "|" KEY_POWER "|" KEY_MODE "|" KEY_TEMP "|" KEY_FANSPEED "|" KEY_SWINGV "|" KEY_SWINGH "|" KEY_QUIET "|" KEY_TURBO "|" KEY_LIGHT "|" KEY_BEEP "|" KEY_ECONO "|" KEY_SLEEP "|" @@ -358,7 +358,7 @@ const char* kClimateTopics = "|" KEY_JSON #endif // MQTT_CLIMATE_JSON ")
"; -const char* kMqttTopics[] = { +static const char* const kMqttTopics[] = { KEY_PROTOCOL, KEY_MODEL, KEY_POWER, KEY_MODE, KEY_TEMP, KEY_FANSPEED, KEY_SWINGV, KEY_SWINGH, KEY_QUIET, KEY_TURBO, KEY_LIGHT, KEY_BEEP, KEY_ECONO, KEY_SLEEP, KEY_FILTER, KEY_CLEAN, KEY_CELSIUS, KEY_RESEND, diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRMQTTServer/IRMQTTServer.ino b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRMQTTServer/IRMQTTServer.ino index fefd743d8..180c4214c 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRMQTTServer/IRMQTTServer.ino +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRMQTTServer/IRMQTTServer.ino @@ -1,6 +1,6 @@ /* * Send & receive arbitrary IR codes via a web server or MQTT. - * Copyright David Conran 2016, 2017, 2018, 2019, 2020 + * Copyright David Conran 2016-2021 * * Copyright: * Code for this has been borrowed from lots of other OpenSource projects & @@ -252,7 +252,8 @@ * - "Middle" * - "Low" * - "Lowest" - * power_command_topic: "ir_server/ac/cmnd/power" + * # `power_command_topic` is probably not needed for most HA configurations + * # power_command_topic: "ir_server/ac/cmnd/power" * mode_command_topic: "ir_server/ac/cmnd/mode" * mode_state_topic: "ir_server/ac/stat/mode" * temperature_command_topic: "ir_server/ac/cmnd/temp" @@ -360,6 +361,12 @@ #include #include +#ifdef ESP32 +#ifdef F +#undef F +#endif // F +#define F(string) string +#endif // ESP32 using irutils::msToString; #if REPORT_VCC @@ -380,7 +387,7 @@ MDNSResponder mdns; WiFiClient espClient; WiFiManager wifiManager; bool flagSaveWifiConfig = false; -char HttpUsername[kUsernameLength + 1] = "admin"; // Default HTT username. +char HttpUsername[kUsernameLength + 1] = "admin"; // Default HTTP username. char HttpPassword[kPasswordLength + 1] = ""; // No HTTP password by default. char Hostname[kHostnameLength + 1] = "ir_server"; // Default hostname. uint16_t *codeArray; @@ -398,14 +405,14 @@ String lastClimateSource; IRrecv *irrecv = NULL; decode_results capture; // Somewhere to store inbound IR messages. int8_t rx_gpio = kDefaultIrRx; -String lastIrReceived = "None"; +String lastIrReceived = FPSTR("None"); uint32_t lastIrReceivedTime = 0; uint32_t irRecvCounter = 0; #endif // IR_RX // Climate stuff IRac *climate[kNrOfIrTxGpios]; -String channel_re = "("; // Will be built later. +String channel_re = FPSTR("("); // Will be built later. uint16_t chan = 0; // The channel to use for the aircon HTML page. TimerMs lastClimateIr = TimerMs(); // When we last sent the IR Climate mesg. @@ -416,8 +423,8 @@ bool hasClimateBeenSent = false; // Has the Climate ever been sent? #if MQTT_ENABLE PubSubClient mqtt_client(espClient); -String lastMqttCmd = "None"; -String lastMqttCmdTopic = "None"; +String lastMqttCmd = FPSTR("None"); +String lastMqttCmdTopic = FPSTR("None"); uint32_t lastMqttCmdTime = 0; uint32_t lastConnectedTime = 0; uint32_t lastDisconnectedTime = 0; @@ -654,7 +661,7 @@ String listOfTxGpios(void) { if (i) result += ", "; result += gpioToString(txGpioTable[i]); if (!found && txGpioTable[i] == getDefaultTxGpio()) { - result += " (default)"; + result += F(" (default)"); found = true; } } @@ -694,7 +701,7 @@ String htmlSelectAcStateProtocol(const String name, const decode_type_t def, break; default: html += htmlOptionItem(String(i), typeToString((decode_type_t)i), - i == def); + i == def); } } } @@ -894,7 +901,7 @@ void handleExamples(void) { #endif // EXAMPLES_ENABLE String htmlSelectBool(const String name, const bool def) { - String html = ""); for (uint16_t i = 0; i < 2; i++) html += htmlOptionItem(IRac::boolToString(i), IRac::boolToString(i), i == def); @@ -903,7 +910,7 @@ String htmlSelectBool(const String name, const bool def) { } String htmlSelectClimateProtocol(const String name, const decode_type_t def) { - String html = ""); for (uint8_t i = 1; i <= decode_type_t::kLastDecodeType; i++) { if (IRac::isProtocolSupported((decode_type_t)i)) { html += htmlOptionItem(String(i), typeToString((decode_type_t)i), @@ -915,14 +922,14 @@ String htmlSelectClimateProtocol(const String name, const decode_type_t def) { } String htmlSelectModel(const String name, const int16_t def) { - String html = ""); for (int16_t i = -1; i <= 6; i++) { String num = String(i); String text; if (i == -1) text = F("Default"); else if (i == 0) - text = F("Unknown"); + text = kUnknownStr; else text = num; html += htmlOptionItem(num, text, i == def); @@ -933,7 +940,7 @@ String htmlSelectModel(const String name, const int16_t def) { String htmlSelectUint(const String name, const uint16_t max, const uint16_t def) { - String html = ""); for (uint16_t i = 0; i < max; i++) { String num = String(i); html += htmlOptionItem(num, num, i == def); @@ -944,7 +951,7 @@ String htmlSelectUint(const String name, const uint16_t max, String htmlSelectGpio(const String name, const int16_t def, const int8_t list[], const int16_t length) { - String html = ": "); for (int16_t i = 0; i < length; i++) { String num = String(list[i]); html += htmlOptionItem(num, list[i] == kGpioUnused ? F("Unused") : num, @@ -956,7 +963,7 @@ String htmlSelectGpio(const String name, const int16_t def, } String htmlSelectMode(const String name, const stdAc::opmode_t def) { - String html = ""); for (int8_t i = -1; i <= (int8_t)stdAc::opmode_t::kLastOpmodeEnum; i++) { String mode = IRac::opmodeToString((stdAc::opmode_t)i); html += htmlOptionItem(mode, mode, (stdAc::opmode_t)i == def); @@ -966,7 +973,7 @@ String htmlSelectMode(const String name, const stdAc::opmode_t def) { } String htmlSelectFanspeed(const String name, const stdAc::fanspeed_t def) { - String html = ""); for (int8_t i = 0; i <= (int8_t)stdAc::fanspeed_t::kLastFanspeedEnum; i++) { String speed = IRac::fanspeedToString((stdAc::fanspeed_t)i); html += htmlOptionItem(speed, speed, (stdAc::fanspeed_t)i == def); @@ -976,7 +983,7 @@ String htmlSelectFanspeed(const String name, const stdAc::fanspeed_t def) { } String htmlSelectSwingv(const String name, const stdAc::swingv_t def) { - String html = ""); for (int8_t i = -1; i <= (int8_t)stdAc::swingv_t::kLastSwingvEnum; i++) { String swing = IRac::swingvToString((stdAc::swingv_t)i); html += htmlOptionItem(swing, swing, (stdAc::swingv_t)i == def); @@ -986,7 +993,7 @@ String htmlSelectSwingv(const String name, const stdAc::swingv_t def) { } String htmlSelectSwingh(const String name, const stdAc::swingh_t def) { - String html = ""); for (int8_t i = -1; i <= (int8_t)stdAc::swingh_t::kLastSwinghEnum; i++) { String swing = IRac::swinghToString((stdAc::swingh_t)i); html += htmlOptionItem(swing, swing, (stdAc::swingh_t)i == def); @@ -1030,84 +1037,85 @@ void handleAirCon(void) { String html = htmlHeader(F("Air Conditioner Control")); html += htmlMenu(); if (kNrOfIrTxGpios > 1) { - html += "" "" - "" "
Climate #" + + "
Climate #") + htmlSelectUint(KEY_CHANNEL, kNrOfIrTxGpios, chan) + - "" + F("" "
" "" - "
"; + "
"); } if (climate[chan] != NULL) { - html += "

Current Settings

" + html += F("

Current Settings

" "
" - "" + - "" - " +const char HTTP_SSPM_VOLTAGE[] PROGMEM = + "{s}" D_VOLTAGE " void SSPMEnergyShow(bool json) { if (!TasmotaGlobal.devices_present) { return; } // Not ready yet if (json) { - ResponseAppend_P(PSTR(",\"SPM\":{\"" D_JSON_TOTAL "\":[")); + ResponseAppend_P(PSTR(",\"SPM\":{\"" D_JSON_ENERGY "\":[")); for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { ResponseAppend_P(PSTR("%s%*_f"), (i>0)?",":"", -1, &Sspm->total[i >>2][i &3]); } - ResponseAppend_P(PSTR("],\"" D_JSON_POWERUSAGE "\":[")); + ResponseAppend_P(PSTR("],\"" D_JSON_ACTIVE_POWERUSAGE "\":[")); for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { ResponseAppend_P(PSTR("%s%*_f"), (i>0)?",":"", Settings->flag2.wattage_resolution, &Sspm->active_power[i >>2][i &3]); } @@ -1069,16 +1064,21 @@ void SSPMEnergyShow(bool json) { } uint32_t module = Sspm->rotate >> 2; uint32_t relay_base = module * 4; - WSContentSend_P(PSTR("{s}" D_SENSOR_RELAY "{m}L%02d / L%02d / L%02d / L%02d{e}"), relay_base +1, relay_base +2, relay_base +3, relay_base +4); - char value_chr[FLOATSZ * 4]; - WSContentSend_PD(HTTP_SNS_VOLTAGE, SSPMEnergyFormat(value_chr, Sspm->voltage[module], Settings->flag2.voltage_resolution, json)); - WSContentSend_PD(HTTP_SNS_CURRENT, SSPMEnergyFormat(value_chr, Sspm->current[module], Settings->flag2.current_resolution, json)); - WSContentSend_PD(HTTP_SNS_POWER, SSPMEnergyFormat(value_chr, Sspm->active_power[module], Settings->flag2.wattage_resolution, json)); - char valu2_chr[FLOATSZ * 4]; - char valu3_chr[FLOATSZ * 4]; - WSContentSend_PD(HTTP_SSPMENERGY_SNS, SSPMEnergyFormat(value_chr, Sspm->apparent_power[module], Settings->flag2.wattage_resolution, json), - SSPMEnergyFormat(valu2_chr, Sspm->reactive_power[module], Settings->flag2.wattage_resolution, json), - SSPMEnergyFormat(valu3_chr, Sspm->total[module], Settings->flag2.energy_resolution, json)); + WSContentSend_P(PSTR("
" D_STR_PROTOCOL "" + + "") + + F("" + "" - "" + "" - "" + "" - "" + "" + F("" "" - "" - "" + "" - "" + "" - "" + "" - "" + "" - "" + "" - "" + "" - "" + "" - "" + "" - "" + "" - "" + "" + F("" "
" D_STR_PROTOCOL "") + htmlSelectClimateProtocol(KEY_PROTOCOL, climate[chan]->next.protocol) + - "
" D_STR_MODEL "" + + F("
" D_STR_MODEL "") + htmlSelectModel(KEY_MODEL, climate[chan]->next.model) + - "
" D_STR_POWER "" + + F("
" D_STR_POWER "") + htmlSelectBool(KEY_POWER, climate[chan]->next.power) + - "
" D_STR_MODE "" + + F("
" D_STR_MODE "") + htmlSelectMode(KEY_MODE, climate[chan]->next.mode) + - "
" D_STR_TEMP "" "" + "step='0.5' value='") + String(climate[chan]->next.degrees, 1) + + F("'>" "
" D_STR_FAN "" + + "
" D_STR_FAN "") + htmlSelectFanspeed(KEY_FANSPEED, climate[chan]->next.fanspeed) + - "
" D_STR_SWINGV "" + + F("
" D_STR_SWINGV "") + htmlSelectSwingv(KEY_SWINGV, climate[chan]->next.swingv) + - "
" D_STR_SWINGH "" + + F("
" D_STR_SWINGH "") + htmlSelectSwingh(KEY_SWINGH, climate[chan]->next.swingh) + - "
" D_STR_QUIET "" + + F("
" D_STR_QUIET "") + htmlSelectBool(KEY_QUIET, climate[chan]->next.quiet) + - "
" D_STR_TURBO "" + + F("
" D_STR_TURBO "") + htmlSelectBool(KEY_TURBO, climate[chan]->next.turbo) + - "
" D_STR_ECONO "" + + F("
" D_STR_ECONO "") + htmlSelectBool(KEY_ECONO, climate[chan]->next.econo) + - "
" D_STR_LIGHT "" + + F("
" D_STR_LIGHT "") + htmlSelectBool(KEY_LIGHT, climate[chan]->next.light) + - "
" D_STR_FILTER "" + + F("
" D_STR_FILTER "") + htmlSelectBool(KEY_FILTER, climate[chan]->next.filter) + - "
" D_STR_CLEAN "" + + F("
" D_STR_CLEAN "") + htmlSelectBool(KEY_CLEAN, climate[chan]->next.clean) + - "
" D_STR_BEEP "" + + F("
" D_STR_BEEP "") + htmlSelectBool(KEY_BEEP, climate[chan]->next.beep) + - "
Force resend" + + F("
Force resend") + htmlSelectBool(KEY_RESEND, false) + - "
" "" - ""; + ""); } html += htmlEnd(); server.send(200, "text/html", html); @@ -1232,124 +1240,127 @@ void handleInfo(void) { String html = htmlHeader(F("IR MQTT server info")); html += htmlMenu(); html += - "

General

" - "

Hostname: " + String(Hostname) + "
" - "IP address: " + WiFi.localIP().toString() + "
" - "MAC address: " + WiFi.macAddress() + "
" - "Booted: " + timeSince(1) + "
" + - "Version: " _MY_VERSION_ "
" + F("

General

" + "

Hostname: ") + String(Hostname) + F("
" + "IP address: ") + WiFi.localIP().toString() + F("
" + "MAC address: ") + WiFi.macAddress() + F("
" + "Booted: ") + timeSince(1) + F("
") + + F("Version: " _MY_VERSION_ "
" "Built: " __DATE__ " " __TIME__ "
" - "Period Offset: " + String(offset) + "us
" + "Period Offset: ") + String(offset) + F("us
" "IR Lib Version: " _IRREMOTEESP8266_VERSION_ "
" #if defined(ESP8266) - "ESP8266 Core Version: " + ESP.getCoreVersion() + "
" - "Free Sketch Space: " + String(maxSketchSpace() >> 10) + "k
" + "ESP8266 Core Version: ") + ESP.getCoreVersion() + F("
" + "Free Sketch Space: ") + String(maxSketchSpace() >> 10) + F("k
" #endif // ESP8266 #if defined(ESP32) - "ESP32 SDK Version: " + ESP.getSdkVersion() + "
" + "ESP32 SDK Version: ") + ESP.getSdkVersion() + F("
" #endif // ESP32 - "Cpu Freq: " + String(ESP.getCpuFreqMHz()) + "MHz
" - "Sanity Check: " + String((_sanity == 0) ? "Ok" : "FAILED") + "
" - "IR Send GPIO(s): " + listOfTxGpios() + "
" + "Cpu Freq: ") + String(ESP.getCpuFreqMHz()) + F("MHz
" + "Sanity Check: ") + String((_sanity == 0) ? F("Ok") : F("FAILED")) + + F("
" + "IR Send GPIO(s): ") + listOfTxGpios() + F("
") + irutils::addBoolToString(kInvertTxOutput, - "Inverting GPIO output", false) + "
" - "Total send requests: " + String(sendReqCounter) + "
" - "Last message sent: " + String(lastSendSucceeded ? "Ok" : "FAILED") + - " (" + timeSince(lastSendTime) + ")
" + F("Inverting GPIO output"), false) + F("
" + "Total send requests: ") + String(sendReqCounter) + F("
" + "Last message sent: ") + String(lastSendSucceeded ? F("Ok") : F("FAILED")) + + F(" (") + timeSince(lastSendTime) + F(")
" #if IR_RX - "IR Recv GPIO: " + gpioToString(rx_gpio) + + "IR Recv GPIO: ") + gpioToString(rx_gpio) + F( #if IR_RX_PULLUP " (pullup)" #endif // IR_RX_PULLUP "
" - "Total IR Received: " + String(irRecvCounter) + "
" - "Last IR Received: " + lastIrReceived + - " (" + timeSince(lastIrReceivedTime) + ")
" + "Total IR Received: ") + String(irRecvCounter) + F("
" + "Last IR Received: ") + lastIrReceived + + F(" (") + timeSince(lastIrReceivedTime) + F(")
" #endif // IR_RX - "Duplicate " D_STR_WIFI " networks: " + - String(HIDE_DUPLICATE_NETWORKS ? "Hide" : "Show") + "
" + "Duplicate " D_STR_WIFI " networks: ") + + String(HIDE_DUPLICATE_NETWORKS ? F("Hide") : F("Show")) + F("
" "Min " D_STR_WIFI " signal required: " #ifdef MIN_SIGNAL_STRENGTH - + String(static_cast(MIN_SIGNAL_STRENGTH)) + + ) + // NOLINT(whitespace/parens) + String(static_cast(MIN_SIGNAL_STRENGTH)) + F( #else // MIN_SIGNAL_STRENGTH "8" #endif // MIN_SIGNAL_STRENGTH "%
" "Serial debugging: " #if DEBUG - + String(isSerialGpioUsedByIr() ? D_STR_OFF : D_STR_ON) + + ) + // NOLINT(whitespace/parens) + String(isSerialGpioUsedByIr() ? D_STR_OFF : D_STR_ON) + F( #else // DEBUG D_STR_OFF #endif // DEBUG "
" #if REPORT_VCC - "Vcc: "; + "Vcc: "); html += vccToString(); - html += "V
" + html += F("V
" #endif // REPORT_VCC "

" #if MQTT_ENABLE "

MQTT Information

" - "

Server: " + String(MqttServer) + ":" + String(MqttPort) + " (" + + "

Server: ") + String(MqttServer) + ":" + String(MqttPort) + F(" (") + (mqtt_client.connected() ? "Connected " + timeSince(lastDisconnectedTime) : "Disconnected " + timeSince(lastConnectedTime)) + - ")
" - "Disconnections: " + String(mqttDisconnectCounter - 1) + "
" - "Buffer Size: " + String(mqtt_client.getBufferSize()) + " bytes
" - "Client id: " + MqttClientId + "
" - "Command topic(s): " + listOfCommandTopics() + "
" - "Acknowledgements topic: " + MqttAck + "
" + F(")

" + "Disconnections: ") + String(mqttDisconnectCounter - 1) + F("
" + "Buffer Size: ") + String(mqtt_client.getBufferSize()) + F(" bytes
" + "Client id: ") + MqttClientId + F("
" + "Command topic(s): ") + listOfCommandTopics() + F("
" + "Acknowledgements topic: ") + MqttAck + F("
" #if IR_RX - "IR Received topic: " + MqttRecv + "
" + "IR Received topic: ") + MqttRecv + F("
" #endif // IR_RX - "Log topic: " + MqttLog + "
" - "LWT topic: " + MqttLwt + "
" - "QoS: " + String(QOS) + "
" + "Log topic: ") + MqttLog + F("
" + "LWT topic: ") + MqttLwt + F("
" + "QoS: ") + String(QOS) + F("
" // lastMqttCmd* is unescaped untrusted input. // Avoid any possible HTML/XSS when displaying it. - "Last MQTT command seen: (topic) '" + + "Last MQTT command seen: (topic) '") + irutils::htmlEscape(lastMqttCmdTopic) + - "' (payload) '" + irutils::htmlEscape(lastMqttCmd) + "' (" + - timeSince(lastMqttCmdTime) + ")
" - "Total published: " + String(mqttSentCounter) + "
" - "Total received: " + String(mqttRecvCounter) + "
" + F("' (payload) '") + irutils::htmlEscape(lastMqttCmd) + F("' (") + + timeSince(lastMqttCmdTime) + F(")
" + "Total published: ") + String(mqttSentCounter) + F("
" + "Total received: ") + String(mqttRecvCounter) + F("
" "

" #endif // MQTT_ENABLE "

Climate Information

" "

" - "IR Send GPIO: " + String(txGpioTable[0]) + "
" - "Last update source: " + lastClimateSource + "
" - "Total sent: " + String(irClimateCounter) + "
" - "Last send: " + String(hasClimateBeenSent ? + "IR Send GPIO: ") + String(txGpioTable[0]) + F("
" + "Last update source: ") + lastClimateSource + F("
" + "Total sent: ") + String(irClimateCounter) + F("
" + "Last send: ") + String(hasClimateBeenSent ? (String(lastClimateSucceeded ? "Ok" : "FAILED") + " (" + timeElapsed(lastClimateIr.elapsed()) + ")") : - "Never") + "
" + "Never") + F("
" #if MQTT_ENABLE - "State listen period: " + msToString(kStatListenPeriodMs) + "
" - "State broadcast period: " + msToString(kBroadcastPeriodMs) + "
" - "Last state broadcast: " + (hasBroadcastBeenSent ? + "State listen period: ") + msToString(kStatListenPeriodMs) + F("
" + "State broadcast period: ") + msToString(kBroadcastPeriodMs) + F("
" + "Last state broadcast: ") + (hasBroadcastBeenSent ? timeElapsed(lastBroadcast.elapsed()) : - String("Never")) + "
" + String(F("Never"))) + F("
" #if MQTT_DISCOVERY_ENABLE - "Last discovery sent: " + (lockMqttBroadcast ? - String("Locked") : + "Last discovery sent: ") + (lockMqttBroadcast ? + String(F("Locked")) : (hasDiscoveryBeenSent ? timeElapsed(lastDiscovery.elapsed()) : - String("Never"))) + - "
" - "Discovery topic: " + MqttDiscovery + "
" + + String(F("Never")))) + + F("
" + "Discovery topic: ") + MqttDiscovery + F("
") + F( #endif // MQTT_DISCOVERY_ENABLE - "Command topics: " + MqttClimate + channel_re + '/' + MQTT_CLIMATE_CMND + - '/' + kClimateTopics + - "State topics: " + MqttClimate + channel_re + '/' + MQTT_CLIMATE_STAT + - '/' + kClimateTopics + + "Command topics: ") + MqttClimate + channel_re + + F("/" MQTT_CLIMATE_CMND "/") + FPSTR(kClimateTopics) + + F("State topics: ") + MqttClimate + channel_re + + F("/" MQTT_CLIMATE_STAT "/") + FPSTR(kClimateTopics) + F( #endif // MQTT_ENABLE "

" // Page footer "

" "(Note: Page will refresh every 60 " D_STR_SECONDS ".)" - "

"; + "

"); html += addJsReloadUrl(kUrlInfo, 60, false); html += htmlEnd(); server.send(200, "text/html", html); @@ -1384,14 +1395,14 @@ bool clearMqttSavedStates(const String topic_base) { for (size_t i = 0; i < sizeof(kMqttTopics) / sizeof(char*); i++) { // Sending a retained "" message to the topic should clear previous values // in theory. - String topic = topic_base + channelStr + '/' + F(MQTT_CLIMATE_STAT) + - '/' + String(kMqttTopics[i]); + String topic = topic_base + channelStr + F("/" MQTT_CLIMATE_STAT "/") + + String(kMqttTopics[i]); success &= mqtt_client.publish(topic.c_str(), "", true); } channelStr = '_' + String(channel); } - String logmesg = "Removing all possible settings saved in MQTT for '" + - topic_base + "' "; + String logmesg = F("Removing all possible settings saved in MQTT for '") + + topic_base + F("' "); logmesg += success ? F("succeeded") : F("failed"); mqttLog(logmesg.c_str()); return success; @@ -1410,13 +1421,13 @@ void handleClearMqtt(void) { htmlHeader(F("Clearing saved info from MQTT"), F("Removing all saved settings for this device from " "MQTT.")) + - "

Device restarting. Try connecting in a few " D_STR_SECONDS ".

" + + F("

Device restarting. Try connecting in a few " D_STR_SECONDS ".

") + addJsReloadUrl(kUrlRoot, 10, true) + htmlEnd()); // Do the clearing. - mqttLog("Clearing all saved settings from MQTT."); + mqttLog(PSTR("Clearing all saved settings from MQTT.")); clearMqttSavedStates(MqttClimate); - doRestart("Rebooting..."); + doRestart(PSTR("Rebooting...")); } #endif // MQTT_ENABLE && MQTT_CLEAR_ENABLE @@ -1438,10 +1449,10 @@ void handleReset(void) { // Do the reset. #if MQTT_ENABLE #if MQTT_CLEAR_ENABLE - mqttLog("Clearing all saved climate settings from MQTT."); + mqttLog(PSTR("Clearing all saved climate settings from MQTT.")); clearMqttSavedStates(MqttClimate); #endif // MQTT_CLEAR_ENABLE - mqttLog("Wiping all saved config settings."); + mqttLog(PSTR("Wiping all saved config settings.")); #endif // MQTT_ENABLE if (mountSpiffs()) { debug("Removing JSON config file"); @@ -1451,7 +1462,7 @@ void handleReset(void) { delay(1000); debug("Reseting wifiManager's settings."); wifiManager.resetSettings(); - doRestart("Rebooting..."); + doRestart(PSTR("Rebooting...")); } // Reboot web page @@ -1465,7 +1476,7 @@ void handleReboot() { #endif server.send(200, "text/html", htmlHeader(F("Device restarting.")) + - "

Try connecting in a few " D_STR_SECONDS ".

" + + F("

Try connecting in a few " D_STR_SECONDS ".

") + addJsReloadUrl(kUrlRoot, kRebootTime, true) + htmlEnd()); doRestart("Reboot requested"); @@ -1484,7 +1495,7 @@ bool parseStringAndSendAirCon(IRsend *irsend, const decode_type_t irType, uint8_t state[kStateSizeMax] = {0}; // All array elements are set to 0. uint16_t stateSize = 0; - if (str.startsWith("0x") || str.startsWith("0X")) + if (str.startsWith(PSTR("0x")) || str.startsWith(PSTR("0X"))) strOffset = 2; // Calculate how many hexadecimal characters there are. uint16_t inputLength = str.length() - strOffset; @@ -1643,8 +1654,9 @@ uint16_t * newCodeArray(const uint16_t size) { // Check we malloc'ed successfully. if (result == NULL) // malloc failed, so give up. doRestart( - "FATAL: Can't allocate memory for an array for a new message! " - "Forcing a reboot!", true); // Send to serial only as we are in low mem + PSTR("FATAL: Can't allocate memory for an array for a new message! " + "Forcing a reboot!"), + true); // Send to serial only as we are in low mem return result; } @@ -1666,7 +1678,7 @@ bool parseStringAndSendGC(IRsend *irsend, const String str) { String tmp_str; // Remove the leading "1:1,1," if present. - if (str.startsWith("1:1,1,")) + if (str.startsWith(PSTR("1:1,1,"))) tmp_str = str.substring(6); else tmp_str = str; @@ -2097,7 +2109,7 @@ void setup(void) { if (isSerialGpioUsedByIr()) Serial.end(); #endif // DEBUG - channel_re.reserve(kNrOfIrTxGpios * 3); + channel_re.reserve(kNrOfIrTxGpios * 3 + 3 + 1); // Initialise all the IR transmitters. for (uint8_t i = 0; i < kNrOfIrTxGpios; i++) { if (txGpioTable[i] == kGpioUnused) { @@ -2195,7 +2207,7 @@ void setup(void) { if (strlen(HttpPassword)) { // Allow if password is set. server.on("/update", HTTP_POST, [](){ #if MQTT_ENABLE - mqttLog("Attempting firmware update & reboot"); + mqttLog(PSTR("Attempting firmware update & reboot")); delay(1000); #endif // MQTT_ENABLE server.send(200, "text/html", @@ -2287,7 +2299,7 @@ void unsubscribing(const String topic_name) { void mqttLog(const char* str) { debug(str); - mqtt_client.publish(MqttLog.c_str(), str); + mqtt_client.publish(MqttLog.c_str(), String(str).c_str()); mqttSentCounter++; } @@ -2313,7 +2325,7 @@ bool reconnect(void) { } if (connected) { // Once connected, publish an announcement... - mqttLog("(Re)Connected."); + mqttLog(PSTR("(Re)Connected.")); // Update Last Will & Testament to say we are back online. mqtt_client.publish(MqttLwt.c_str(), kLwtOnline, true); @@ -2364,12 +2376,13 @@ void handleSendMqttDiscovery(void) { server.send(200, "text/html", htmlHeader(F("Sending MQTT Discovery message")) + htmlMenu() + - "

The Home Assistant MQTT Discovery message is being sent to topic: " + - MqttDiscovery + ". It will show up in Home Assistant in a few seconds." + F("

The Home Assistant MQTT Discovery message is being sent to topic: ") + + MqttDiscovery + + F(". It will show up in Home Assistant in a few seconds." "

" "

Warning!

" "

Home Assistant's config for this device is reset each time this is " - " is sent.

" + + " is sent.

") + addJsReloadUrl(kUrlRoot, kRebootTime, true) + htmlEnd()); sendMQTTDiscovery(MqttDiscovery.c_str()); @@ -2416,8 +2429,8 @@ void receivingMQTT(String const topic_name, String const callback_str) { // Or is for a specific ac/climate channel. e.g. "*/ac_[1-9]" debug(("Checking for channel number in " + topic_name).c_str()); for (uint16_t i = 0; i < kNrOfIrTxGpios; i++) { - if (topic_name.endsWith("_" + String(i)) || - (i > 0 && topic_name.startsWith(MqttClimate + "_" + String(i)))) { + if (topic_name.endsWith('_' + String(i)) || + (i > 0 && topic_name.startsWith(MqttClimate + '_' + String(i)))) { channel = i; break; } @@ -2425,8 +2438,8 @@ void receivingMQTT(String const topic_name, String const callback_str) { debug(("Channel = " + String(channel)).c_str()); // Is it a climate topic? if (topic_name.startsWith(MqttClimate)) { - String alt_cmnd_topic = MqttClimate + "_" + String(channel) + '/' + - MQTT_CLIMATE_CMND + '/'; + String alt_cmnd_topic = MqttClimate + '_' + String(channel) + + F("/" MQTT_CLIMATE_CMND "/"); // Also accept climate commands on the '*_0' channel. String cmnd_topic = topic_name.startsWith(alt_cmnd_topic) ? alt_cmnd_topic : MqttClimateCmnd; @@ -2440,7 +2453,7 @@ void receivingMQTT(String const topic_name, String const callback_str) { if (topic_name.equals(cmnd_topic + KEY_RESEND) && callback_str.equalsIgnoreCase(KEY_RESEND)) { force_resend = true; - mqttLog("Climate resend requested."); + mqttLog(PSTR("Climate resend requested.")); } if (sendClimate(stat_topic, true, false, force_resend, true, climate[channel]) && !force_resend) @@ -2548,10 +2561,15 @@ void mqttCallback(char* topic, byte* payload, unsigned int length) { void sendMQTTDiscovery(const char *topic) { if (mqtt_client.publish( topic, String( - "{" - "\"~\":\"" + MqttClimate + "\"," - "\"name\":\"" + MqttHAName + "\"," + F("{" + "\"~\":\"") + MqttClimate + F("\"," + "\"name\":\"") + MqttHAName + F("\"," +#if (!MQTT_CLIMATE_HA_MODE) + // Typically we don't need or use the power command topic if we are using + // our Home Assistant Climate compatiblity mode. It causes odd behaviour + // if both are used. "\"pow_cmd_t\":\"~/" MQTT_CLIMATE_CMND "/" KEY_POWER "\"," +#endif // !MQTT_CLIMATE_HA_MODE "\"mode_cmd_t\":\"~/" MQTT_CLIMATE_CMND "/" KEY_MODE "\"," "\"mode_stat_t\":\"~/" MQTT_CLIMATE_STAT "/" KEY_MODE "\"," // I don't know why, but the modes need to be lower case to work with @@ -2571,22 +2589,22 @@ void sendMQTTDiscovery(const char *topic) { "\"swing_modes\":[\"" D_STR_OFF "\",\"" D_STR_AUTO "\",\"" D_STR_HIGHEST "\",\"" D_STR_HIGH "\",\"" D_STR_MIDDLE "\",\"" D_STR_LOW "\",\"" D_STR_LOWEST "\"]," - "\"uniq_id\":\"" + MqttUniqueId + "\"," + "\"uniq_id\":\"") + MqttUniqueId + F("\"," "\"device\":{" - "\"identifiers\":[\"" + MqttUniqueId + "\"]," - "\"connections\":[[\"mac\",\"" + WiFi.macAddress() + "\"]]," + "\"identifiers\":[\"") + MqttUniqueId + F("\"]," + "\"connections\":[[\"mac\",\"") + WiFi.macAddress() + F("\"]]," "\"manufacturer\":\"IRremoteESP8266\"," "\"model\":\"IRMQTTServer\"," - "\"name\":\"" + Hostname + "\"," + "\"name\":\"") + Hostname + F("\"," "\"sw_version\":\"" _MY_VERSION_ "\"" "}" - "}").c_str(), true)) { - mqttLog("MQTT climate discovery successful sent."); + "}")).c_str(), true)) { + mqttLog(PSTR("MQTT climate discovery successful sent.")); hasDiscoveryBeenSent = true; lastDiscovery.reset(); mqttSentCounter++; } else { - mqttLog("MQTT climate discovery FAILED to send."); + mqttLog(PSTR("MQTT climate discovery FAILED to send.")); } } #endif // MQTT_DISCOVERY_ENABLE @@ -2616,11 +2634,12 @@ void loop(void) { lastReconnectAttempt = 0; wasConnected = true; if (boot) { - mqttLog("IRMQTTServer " _MY_VERSION_ " just booted"); + mqttLog(PSTR("IRMQTTServer " _MY_VERSION_ " just booted")); boot = false; } else { mqttLog(String( - "IRMQTTServer just (re)connected to MQTT. Lost connection about " + F("IRMQTTServer just (re)connected to MQTT. " + "Lost connection about ") + timeSince(lastConnectedTime)).c_str()); } lastConnectedTime = now; @@ -2628,7 +2647,7 @@ void loop(void) { if (lockMqttBroadcast) { // Attempt to fetch back any Climate state stored in MQTT retained // messages on the MQTT broker. - mqttLog("Started listening for previous state."); + mqttLog(PSTR("Started listening for previous state.")); for (uint16_t i = 0; i < kNrOfIrTxGpios; i++) subscribing(genStatTopic(i) + '+'); statListenTime.reset(); @@ -2648,10 +2667,10 @@ void loop(void) { sendClimate(stat_topic, true, false, false, MQTT_CLIMATE_IR_SEND_ON_RESTART, climate[i]); lastClimateSource = F("MQTT (via retain)"); - mqttLog("The state was recovered from MQTT broker."); + mqttLog(PSTR("The state was recovered from MQTT broker.")); } } - mqttLog("Finished listening for previous state."); + mqttLog(PSTR("Finished listening for previous state.")); lockMqttBroadcast = false; // Release the lock so we can broadcast again. } // Periodically send all of the climate state via MQTT. @@ -2671,17 +2690,17 @@ void loop(void) { resultToHexidecimal(&capture); #if REPORT_RAW_UNKNOWNS if (capture.decode_type == UNKNOWN) { - lastIrReceived += ";"; + lastIrReceived += ';'; for (uint16_t i = 1; i < capture.rawlen; i++) { uint32_t usecs; for (usecs = capture.rawbuf[i] * kRawTick; usecs > UINT16_MAX; usecs -= UINT16_MAX) { lastIrReceived += uint64ToString(UINT16_MAX); - lastIrReceived += ",0,"; + lastIrReceived += F(",0,"); } lastIrReceived += uint64ToString(usecs, 10); if (i < capture.rawlen - 1) - lastIrReceived += ","; + lastIrReceived += ','; } } #endif // REPORT_RAW_UNKNOWNS @@ -2875,10 +2894,10 @@ void sendJsonState(const stdAc::state_t state, const String topic, json[KEY_PROTOCOL] = typeToString(state.protocol); json[KEY_MODEL] = state.model; json[KEY_POWER] = IRac::boolToString(state.power); - json[KEY_MODE] = IRac::opmodeToString(state.mode); + json[KEY_MODE] = IRac::opmodeToString(state.mode, ha_mode); // Home Assistant wants mode to be off if power is also off & vice-versa. if (ha_mode && (state.mode == stdAc::opmode_t::kOff || !state.power)) { - json[KEY_MODE] = IRac::opmodeToString(stdAc::opmode_t::kOff); + json[KEY_MODE] = IRac::opmodeToString(stdAc::opmode_t::kOff, ha_mode); json[KEY_POWER] = IRac::boolToString(false); } json[KEY_CELSIUS] = IRac::boolToString(state.celsius); @@ -2965,45 +2984,45 @@ void updateClimate(stdAc::state_t *state, const String str, *state = jsonToState(*state, payload.c_str()); else #endif // MQTT_CLIMATE_JSON - if (str.equals(prefix + KEY_PROTOCOL)) { + if (str.equals(prefix + F(KEY_PROTOCOL))) { state->protocol = strToDecodeType(payload.c_str()); - } else if (str.equals(prefix + KEY_MODEL)) { + } else if (str.equals(prefix + F(KEY_MODEL))) { state->model = IRac::strToModel(payload.c_str()); - } else if (str.equals(prefix + KEY_POWER)) { + } else if (str.equals(prefix + F(KEY_POWER))) { state->power = IRac::strToBool(payload.c_str()); #if MQTT_CLIMATE_HA_MODE if (!state->power) state->mode = stdAc::opmode_t::kOff; #endif // MQTT_CLIMATE_HA_MODE - } else if (str.equals(prefix + KEY_MODE)) { + } else if (str.equals(prefix + F(KEY_MODE))) { state->mode = IRac::strToOpmode(payload.c_str()); #if MQTT_CLIMATE_HA_MODE state->power = (state->mode != stdAc::opmode_t::kOff); #endif // MQTT_CLIMATE_HA_MODE - } else if (str.equals(prefix + KEY_TEMP)) { + } else if (str.equals(prefix + F(KEY_TEMP))) { state->degrees = payload.toFloat(); - } else if (str.equals(prefix + KEY_FANSPEED)) { + } else if (str.equals(prefix + F(KEY_FANSPEED))) { state->fanspeed = IRac::strToFanspeed(payload.c_str()); - } else if (str.equals(prefix + KEY_SWINGV)) { + } else if (str.equals(prefix + F(KEY_SWINGV))) { state->swingv = IRac::strToSwingV(payload.c_str()); - } else if (str.equals(prefix + KEY_SWINGH)) { + } else if (str.equals(prefix + F(KEY_SWINGH))) { state->swingh = IRac::strToSwingH(payload.c_str()); - } else if (str.equals(prefix + KEY_QUIET)) { + } else if (str.equals(prefix + F(KEY_QUIET))) { state->quiet = IRac::strToBool(payload.c_str()); - } else if (str.equals(prefix + KEY_TURBO)) { + } else if (str.equals(prefix + F(KEY_TURBO))) { state->turbo = IRac::strToBool(payload.c_str()); - } else if (str.equals(prefix + KEY_ECONO)) { + } else if (str.equals(prefix + F(KEY_ECONO))) { state->econo = IRac::strToBool(payload.c_str()); - } else if (str.equals(prefix + KEY_LIGHT)) { + } else if (str.equals(prefix + F(KEY_LIGHT))) { state->light = IRac::strToBool(payload.c_str()); - } else if (str.equals(prefix + KEY_BEEP)) { + } else if (str.equals(prefix + F(KEY_BEEP))) { state->beep = IRac::strToBool(payload.c_str()); - } else if (str.equals(prefix + KEY_FILTER)) { + } else if (str.equals(prefix + F(KEY_FILTER))) { state->filter = IRac::strToBool(payload.c_str()); - } else if (str.equals(prefix + KEY_CLEAN)) { + } else if (str.equals(prefix + F(KEY_CLEAN))) { state->clean = IRac::strToBool(payload.c_str()); - } else if (str.equals(prefix + KEY_CELSIUS)) { + } else if (str.equals(prefix + F(KEY_CELSIUS))) { state->celsius = IRac::strToBool(payload.c_str()); - } else if (str.equals(prefix + KEY_SLEEP)) { + } else if (str.equals(prefix + F(KEY_SLEEP))) { state->sleep = payload.toInt(); } } @@ -3024,7 +3043,11 @@ bool sendClimate(const String topic_prefix, const bool retain, diff = true; success &= sendInt(topic_prefix + KEY_MODEL, next.model, retain); } +#ifdef MQTT_CLIMATE_HA_MODE + String mode_str = IRac::opmodeToString(next.mode, MQTT_CLIMATE_HA_MODE); +#else // MQTT_CLIMATE_HA_MODE String mode_str = IRac::opmodeToString(next.mode); +#endif // MQTT_CLIMATE_HA_MODE // I don't know why, but the modes need to be lower case to work with // Home Assistant & Google Home. mode_str.toLowerCase(); diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRrecvDumpV2/platformio.ini b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRrecvDumpV2/platformio.ini index 0063a1133..b56304f66 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRrecvDumpV2/platformio.ini +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRrecvDumpV2/platformio.ini @@ -52,6 +52,12 @@ build_flags = -D_IR_LOCALE_=it-IT ; Italian [env:pt-BR] build_flags = -D_IR_LOCALE_=pt-BR ; Portuguese (Brazilian) +[env:ru-RU] +build_flags = -D_IR_LOCALE_=ru-RU ; Russian + +[env:sv-SE] +build_flags = -D_IR_LOCALE_=sv-SE ; Swedish + [env:zh-CN] build_flags = -D_IR_LOCALE_=zh-CN ; Chinese (Simplified) diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRrecvDumpV3/platformio.ini b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRrecvDumpV3/platformio.ini index 95a90ac86..e5df92876 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRrecvDumpV3/platformio.ini +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/examples/IRrecvDumpV3/platformio.ini @@ -49,5 +49,14 @@ build_flags = -D_IR_LOCALE_=fr-FR ; French [env:it-IT] build_flags = -D_IR_LOCALE_=it-IT ; Italian +[env:pt-BR] +build_flags = -D_IR_LOCALE_=pt-BR ; Portuguese (Brazilian) + +[env:ru-RU] +build_flags = -D_IR_LOCALE_=ru-RU ; Russian + +[env:sv-SE] +build_flags = -D_IR_LOCALE_=sv-SE ; Swedish + [env:zh-CN] build_flags = -D_IR_LOCALE_=zh-CN ; Chinese (Simplified) diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/keywords.txt b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/keywords.txt index fefce8d9d..592b5d99b 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/keywords.txt +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/keywords.txt @@ -52,6 +52,7 @@ IRKelonAc KEYWORD1 IRKelvinatorAC KEYWORD1 IRLgAc KEYWORD1 IRMideaAC KEYWORD1 +IRMirageAc KEYWORD1 IRMitsubishi112 KEYWORD1 IRMitsubishi136 KEYWORD1 IRMitsubishiAC KEYWORD1 @@ -60,6 +61,7 @@ IRMitsubishiHeavy88Ac KEYWORD1 IRNeoclimaAc KEYWORD1 IRPanasonicAc KEYWORD1 IRPanasonicAc32 KEYWORD1 +IRRhossAc KEYWORD1 IRSamsungAc KEYWORD1 IRSanyoAc KEYWORD1 IRSanyoAc88 KEYWORD1 @@ -85,16 +87,19 @@ decode_type_t KEYWORD1 fanspeed_t KEYWORD1 fujitsu_ac_remote_model_t KEYWORD1 gree_ac_remote_model_t KEYWORD1 +haier_ac176_remote_model_t KEYWORD1 hitachi_ac1_remote_model_t KEYWORD1 irparams_t KEYWORD1 lg_ac_remote_model_t KEYWORD1 match_result_t KEYWORD1 +mirage_ac_remote_model_t KEYWORD1 opmode_t KEYWORD1 panasonic_ac_remote_model_t KEYWORD1 sharp_ac_remote_model_t KEYWORD1 state_t KEYWORD1 swingh_t KEYWORD1 swingv_t KEYWORD1 +tcl_ac_remote_model_t KEYWORD1 voltas_ac_remote_model_t KEYWORD1 whirlpool_ac_remote_model_t KEYWORD1 @@ -107,6 +112,8 @@ _cancelOffTimer KEYWORD2 _cancelOnTimer KEYWORD2 _delayMicroseconds KEYWORD2 _getEconoToggle KEYWORD2 +_getOffTimer KEYWORD2 +_getOnTimer KEYWORD2 _getTime KEYWORD2 _getTimer KEYWORD2 _isAKB73757604 KEYWORD2 @@ -117,6 +124,9 @@ _restoreState KEYWORD2 _sendSony KEYWORD2 _setEconoToggle KEYWORD2 _setMode KEYWORD2 +_setOffTimer KEYWORD2 +_setOnTimer KEYWORD2 +_setSleepTimer KEYWORD2 _setTemp KEYWORD2 _setTime KEYWORD2 _setTimer KEYWORD2 @@ -135,6 +145,7 @@ addSwingHToString KEYWORD2 addSwingVToString KEYWORD2 addTempFloatToString KEYWORD2 addTempToString KEYWORD2 +addToggleToString KEYWORD2 adjustRepeat KEYWORD2 airwell KEYWORD2 amcor KEYWORD2 @@ -189,10 +200,12 @@ daikin2 KEYWORD2 daikin216 KEYWORD2 daikin64 KEYWORD2 decode KEYWORD2 +decodeAirton KEYWORD2 decodeAirwell KEYWORD2 decodeAiwaRCT501 KEYWORD2 decodeAmcor KEYWORD2 decodeArgo KEYWORD2 +decodeArris KEYWORD2 decodeBose KEYWORD2 decodeCOOLIX KEYWORD2 decodeCarrierAC KEYWORD2 @@ -258,6 +271,7 @@ decodePioneer KEYWORD2 decodeRC5 KEYWORD2 decodeRC6 KEYWORD2 decodeRCMM KEYWORD2 +decodeRhoss KEYWORD2 decodeSAMSUNG KEYWORD2 decodeSamsung36 KEYWORD2 decodeSamsungAC KEYWORD2 @@ -298,6 +312,7 @@ enableIROut KEYWORD2 enableOffTimer KEYWORD2 enableOnTimer KEYWORD2 enableSleepTimer KEYWORD2 +encodeArris KEYWORD2 encodeDoshisha KEYWORD2 encodeJVC KEYWORD2 encodeLG KEYWORD2 @@ -319,6 +334,7 @@ fahrenheitToCelsius KEYWORD2 fanspeedToString KEYWORD2 fixChecksum KEYWORD2 fixup KEYWORD2 +fromCommon KEYWORD2 fujitsu KEYWORD2 get10CHeat KEYWORD2 get3D KEYWORD2 @@ -331,6 +347,7 @@ getBufSize KEYWORD2 getButton KEYWORD2 getCelsius KEYWORD2 getClean KEYWORD2 +getCleanToggle KEYWORD2 getClock KEYWORD2 getCmd KEYWORD2 getComfort KEYWORD2 @@ -367,6 +384,7 @@ getIonFilter KEYWORD2 getLed KEYWORD2 getLight KEYWORD2 getLightToggle KEYWORD2 +getLock KEYWORD2 getMax KEYWORD2 getMode KEYWORD2 getMold KEYWORD2 @@ -396,9 +414,11 @@ getSectionByte KEYWORD2 getSectionChecksum KEYWORD2 getSensor KEYWORD2 getSensorTemp KEYWORD2 +getSensorUpdate KEYWORD2 getSilent KEYWORD2 getSleep KEYWORD2 getSleepTime KEYWORD2 +getSleepTimer KEYWORD2 getSleepTimerEnabled KEYWORD2 getSpecial KEYWORD2 getSpeed KEYWORD2 @@ -481,6 +501,7 @@ isSwingH KEYWORD2 isSwingV KEYWORD2 isSwingVStep KEYWORD2 isSwingVToggle KEYWORD2 +isTcl KEYWORD2 isTimeCommand KEYWORD2 isTimerActive KEYWORD2 isTurboToggle KEYWORD2 @@ -509,6 +530,7 @@ matchSpaceRange KEYWORD2 midea KEYWORD2 minRepeats KEYWORD2 minsToString KEYWORD2 +mirage KEYWORD2 mitsubishi KEYWORD2 mitsubishi112 KEYWORD2 mitsubishi136 KEYWORD2 @@ -532,15 +554,18 @@ resultToSourceCode KEYWORD2 resultToTimingInfo KEYWORD2 resume KEYWORD2 reverseBits KEYWORD2 +rhoss KEYWORD2 samsung KEYWORD2 sanyo KEYWORD2 sanyo88 KEYWORD2 send KEYWORD2 sendAc KEYWORD2 +sendAirton KEYWORD2 sendAirwell KEYWORD2 sendAiwaRCT501 KEYWORD2 sendAmcor KEYWORD2 sendArgo KEYWORD2 +sendArris KEYWORD2 sendBose KEYWORD2 sendCOOLIX KEYWORD2 sendCarrierAC KEYWORD2 @@ -621,6 +646,7 @@ sendRC5 KEYWORD2 sendRC6 KEYWORD2 sendRCMM KEYWORD2 sendRaw KEYWORD2 +sendRhoss KEYWORD2 sendSAMSUNG KEYWORD2 sendSamsung36 KEYWORD2 sendSamsungAC KEYWORD2 @@ -662,6 +688,7 @@ setBreeze KEYWORD2 setButton KEYWORD2 setCelsius KEYWORD2 setClean KEYWORD2 +setCleanToggle KEYWORD2 setClock KEYWORD2 setCmd KEYWORD2 setComfort KEYWORD2 @@ -697,6 +724,7 @@ setIonFilter KEYWORD2 setLed KEYWORD2 setLight KEYWORD2 setLightToggle KEYWORD2 +setLock KEYWORD2 setMax KEYWORD2 setMode KEYWORD2 setModel KEYWORD2 @@ -725,6 +753,7 @@ setSave KEYWORD2 setSensor KEYWORD2 setSensorTemp KEYWORD2 setSensorTempRaw KEYWORD2 +setSensorUpdate KEYWORD2 setSilent KEYWORD2 setSleep KEYWORD2 setSleepTimer KEYWORD2 @@ -791,6 +820,7 @@ teco KEYWORD2 ticksHigh KEYWORD2 ticksLow KEYWORD2 toString KEYWORD2 +toggleArrisRelease KEYWORD2 toggleRC5 KEYWORD2 toggleRC6 KEYWORD2 toggleSwingHoriz KEYWORD2 @@ -821,6 +851,7 @@ xorBytes KEYWORD2 A705 LITERAL1 A903 LITERAL1 A907 LITERAL1 +AIRTON LITERAL1 AIRWELL LITERAL1 AIWA_RC_T501 LITERAL1 AIWA_RC_T501_BITS LITERAL1 @@ -857,6 +888,7 @@ ARJW2 LITERAL1 ARRAH2E LITERAL1 ARREB1E LITERAL1 ARREW4E LITERAL1 +ARRIS LITERAL1 ARRY4 LITERAL1 BOSE LITERAL1 CARRIER_AC LITERAL1 @@ -887,10 +919,12 @@ DAIKIN_HEAT LITERAL1 DAIKIN_MAX_TEMP LITERAL1 DAIKIN_MIN_TEMP LITERAL1 DECODE_AC LITERAL1 +DECODE_AIRTON LITERAL1 DECODE_AIRWELL LITERAL1 DECODE_AIWA_RC_T501 LITERAL1 DECODE_AMCOR LITERAL1 DECODE_ARGO LITERAL1 +DECODE_ARRIS LITERAL1 DECODE_BOSE LITERAL1 DECODE_CARRIER_AC LITERAL1 DECODE_CARRIER_AC40 LITERAL1 @@ -961,6 +995,7 @@ DECODE_PRONTO LITERAL1 DECODE_RC5 LITERAL1 DECODE_RC6 LITERAL1 DECODE_RCMM LITERAL1 +DECODE_RHOSS LITERAL1 DECODE_SAMSUNG LITERAL1 DECODE_SAMSUNG36 LITERAL1 DECODE_SAMSUNG_AC LITERAL1 @@ -1054,6 +1089,7 @@ GREE_SWING_MIDDLE_DOWN LITERAL1 GREE_SWING_MIDDLE_UP LITERAL1 GREE_SWING_UP LITERAL1 GREE_SWING_UP_AUTO LITERAL1 +GZ055BE1 LITERAL1 HAIER_AC LITERAL1 HAIER_AC176 LITERAL1 HAIER_AC_AUTO LITERAL1 @@ -1063,7 +1099,7 @@ HAIER_AC_CMD_MODE LITERAL1 HAIER_AC_CMD_OFF LITERAL1 HAIER_AC_CMD_ON LITERAL1 HAIER_AC_CMD_SLEEP LITERAL1 -HAIER_AC_CMD_SWING LITERAL1 +HAIER_AC_CMD_SWINGV LITERAL1 HAIER_AC_CMD_TEMP_DOWN LITERAL1 HAIER_AC_CMD_TEMP_UP LITERAL1 HAIER_AC_CMD_TIMER_CANCEL LITERAL1 @@ -1080,10 +1116,10 @@ HAIER_AC_HEAT LITERAL1 HAIER_AC_MAX_TEMP LITERAL1 HAIER_AC_MIN_TEMP LITERAL1 HAIER_AC_STATE_LENGTH LITERAL1 -HAIER_AC_SWING_CHG LITERAL1 -HAIER_AC_SWING_DOWN LITERAL1 -HAIER_AC_SWING_OFF LITERAL1 -HAIER_AC_SWING_UP LITERAL1 +HAIER_AC_SWINGV_CHG LITERAL1 +HAIER_AC_SWINGV_DOWN LITERAL1 +HAIER_AC_SWINGV_OFF LITERAL1 +HAIER_AC_SWINGV_UP LITERAL1 HAIER_AC_YRW02 LITERAL1 HAIER_AC_YRW02_AUTO LITERAL1 HAIER_AC_YRW02_BUTTON_FAN LITERAL1 @@ -1110,8 +1146,6 @@ HAIER_AC_YRW02_SWING_DOWN LITERAL1 HAIER_AC_YRW02_SWING_MIDDLE LITERAL1 HAIER_AC_YRW02_SWING_OFF LITERAL1 HAIER_AC_YRW02_SWING_TOP LITERAL1 -HAIER_AC_YRW02_TURBO_HIGH LITERAL1 -HAIER_AC_YRW02_TURBO_LOW LITERAL1 HAIER_AC_YRW02_TURBO_OFF LITERAL1 HIGH LITERAL1 HITACHI_AC LITERAL1 @@ -1144,6 +1178,8 @@ KELVINATOR_HEAT LITERAL1 KELVINATOR_MAX_TEMP LITERAL1 KELVINATOR_MIN_TEMP LITERAL1 KELVINATOR_STATE_LENGTH LITERAL1 +KKG29AC1 LITERAL1 +KKG9AC1 LITERAL1 LASERTAG LITERAL1 LASERTAG_BITS LITERAL1 LEGOPF LITERAL1 @@ -1224,6 +1260,7 @@ RC6_36_BITS LITERAL1 RC6_MODE0_BITS LITERAL1 RCMM LITERAL1 RCMM_BITS LITERAL1 +RHOSS LITERAL1 R_LT0541_HTA_A LITERAL1 R_LT0541_HTA_B LITERAL1 SAMSUNG LITERAL1 @@ -1236,10 +1273,12 @@ SANYO_AC88 LITERAL1 SANYO_LC7461 LITERAL1 SANYO_LC7461_BITS LITERAL1 SANYO_SA8650B_BITS LITERAL1 +SEND_AIRTON LITERAL1 SEND_AIRWELL LITERAL1 SEND_AIWA_RC_T501 LITERAL1 SEND_AMCOR LITERAL1 SEND_ARGO LITERAL1 +SEND_ARRIS LITERAL1 SEND_BOSE LITERAL1 SEND_CARRIER_AC LITERAL1 SEND_CARRIER_AC40 LITERAL1 @@ -1310,6 +1349,7 @@ SEND_RAW LITERAL1 SEND_RC5 LITERAL1 SEND_RC6 LITERAL1 SEND_RCMM LITERAL1 +SEND_RHOSS LITERAL1 SEND_SAMSUNG LITERAL1 SEND_SAMSUNG36 LITERAL1 SEND_SAMSUNG_AC LITERAL1 @@ -1347,6 +1387,7 @@ SONY_15_BITS LITERAL1 SONY_20_BITS LITERAL1 SONY_38K LITERAL1 SYMPHONY LITERAL1 +TAC09CHSD LITERAL1 TCL112AC LITERAL1 TECHNIBEL_AC LITERAL1 TECO LITERAL1 @@ -1381,6 +1422,8 @@ TRUMA LITERAL1 UNKNOWN LITERAL1 UNUSED LITERAL1 USE_IRAM_ATTR LITERAL1 +V9014557_A LITERAL1 +V9014557_B LITERAL1 VESTEL_AC LITERAL1 VOLTAS LITERAL1 WHIRLPOOL_AC LITERAL1 @@ -1390,11 +1433,25 @@ XMP LITERAL1 YAW1F LITERAL1 YBOFB LITERAL1 ZEPEAL LITERAL1 +k0Str LITERAL1 k10CHeatStr LITERAL1 +k122lzfStr LITERAL1 +k1Str LITERAL1 k3DStr LITERAL1 k6thSenseStr LITERAL1 k8CHeatStr LITERAL1 +kA705Str LITERAL1 +kA903Str LITERAL1 +kA907Str LITERAL1 kAirFlowStr LITERAL1 +kAirtonBitMark LITERAL1 +kAirtonBits LITERAL1 +kAirtonDefaultRepeat LITERAL1 +kAirtonFreq LITERAL1 +kAirtonHdrMark LITERAL1 +kAirtonHdrSpace LITERAL1 +kAirtonOneSpace LITERAL1 +kAirtonZeroSpace LITERAL1 kAirwellAuto LITERAL1 kAirwellBits LITERAL1 kAirwellCool LITERAL1 @@ -1420,6 +1477,9 @@ kAiwaRcT501PostBits LITERAL1 kAiwaRcT501PostData LITERAL1 kAiwaRcT501PreBits LITERAL1 kAiwaRcT501PreData LITERAL1 +kAkb73757604Str LITERAL1 +kAkb74955603Str LITERAL1 +kAkb75215403Str LITERAL1 kAllProtocolNamesStr LITERAL1 kAlokaBits LITERAL1 kAlokaLedBlue LITERAL1 @@ -1464,6 +1524,7 @@ kAmcorTolerance LITERAL1 kAmcorVentOn LITERAL1 kAmcorZeroMark LITERAL1 kAmcorZeroSpace LITERAL1 +kArdb1Str LITERAL1 kArgoAuto LITERAL1 kArgoBitMark LITERAL1 kArgoBits LITERAL1 @@ -1497,6 +1558,21 @@ kArgoOneSpace LITERAL1 kArgoStateLength LITERAL1 kArgoTempDelta LITERAL1 kArgoZeroSpace LITERAL1 +kArjw2Str LITERAL1 +kArrah2eStr LITERAL1 +kArreb1eStr LITERAL1 +kArrew4eStr LITERAL1 +kArrisBits LITERAL1 +kArrisChecksumSize LITERAL1 +kArrisCommandSize LITERAL1 +kArrisGapSpace LITERAL1 +kArrisHalfClockPeriod LITERAL1 +kArrisHdrMark LITERAL1 +kArrisHdrSpace LITERAL1 +kArrisOverhead LITERAL1 +kArrisReleaseBit LITERAL1 +kArrisReleaseToggle LITERAL1 +kArry4Str LITERAL1 kAuto LITERAL1 kAutoStr LITERAL1 kAutomaticStr LITERAL1 @@ -1558,6 +1634,7 @@ kCelsiusStr LITERAL1 kCentreStr LITERAL1 kChangeStr LITERAL1 kCirculateStr LITERAL1 +kCkpStr LITERAL1 kCleanStr LITERAL1 kClockStr LITERAL1 kCodeStr LITERAL1 @@ -1567,6 +1644,7 @@ kCommaSpaceStr LITERAL1 kCommandStr LITERAL1 kCool LITERAL1 kCoolStr LITERAL1 +kCoolingStr LITERAL1 kCoolixAuto LITERAL1 kCoolixBitMark LITERAL1 kCoolixBitMarkTicks LITERAL1 @@ -1866,10 +1944,12 @@ kDaikinSwingOn LITERAL1 kDaikinTolerance LITERAL1 kDaikinUnusedTime LITERAL1 kDaikinZeroSpace LITERAL1 +kDashStr LITERAL1 kDayStr LITERAL1 kDaysStr LITERAL1 kDefaultESP32Timer LITERAL1 kDefaultMessageGap LITERAL1 +kDehumidifyStr LITERAL1 kDelonghiAcAuto LITERAL1 kDelonghiAcBitMark LITERAL1 kDelonghiAcBits LITERAL1 @@ -1914,6 +1994,9 @@ kDenonOneSpaceTicks LITERAL1 kDenonTick LITERAL1 kDenonZeroSpace LITERAL1 kDenonZeroSpaceTicks LITERAL1 +kDg11j104Str LITERAL1 +kDg11j13aStr LITERAL1 +kDg11j191Str LITERAL1 kDishBitMark LITERAL1 kDishBitMarkTicks LITERAL1 kDishBits LITERAL1 @@ -1930,6 +2013,7 @@ kDishTick LITERAL1 kDishZeroSpace LITERAL1 kDishZeroSpaceTicks LITERAL1 kDisplayTempStr LITERAL1 +kDkeStr LITERAL1 kDoshishaBitMark LITERAL1 kDoshishaBits LITERAL1 kDoshishaHdrMark LITERAL1 @@ -1939,6 +2023,7 @@ kDoshishaZeroSpace LITERAL1 kDownStr LITERAL1 kDry LITERAL1 kDryStr LITERAL1 +kDryingStr LITERAL1 kDutyDefault LITERAL1 kDutyMax LITERAL1 kEcoclimAuto LITERAL1 @@ -1992,6 +2077,9 @@ kElectraAcMessageGap LITERAL1 kElectraAcMinRepeat LITERAL1 kElectraAcMinTemp LITERAL1 kElectraAcOneSpace LITERAL1 +kElectraAcSensorMaxTemp LITERAL1 +kElectraAcSensorMinTemp LITERAL1 +kElectraAcSensorTempDelta LITERAL1 kElectraAcStateLength LITERAL1 kElectraAcSwingOff LITERAL1 kElectraAcSwingOn LITERAL1 @@ -2008,8 +2096,11 @@ kEyeAutoStr LITERAL1 kEyeStr LITERAL1 kFalseStr LITERAL1 kFan LITERAL1 +kFanOnlyNoSpaceStr LITERAL1 kFanOnlyStr LITERAL1 +kFanOnlyWithSpaceStr LITERAL1 kFanStr LITERAL1 +kFan_OnlyStr LITERAL1 kFastStr LITERAL1 kFilterStr LITERAL1 kFixedStr LITERAL1 @@ -2064,6 +2155,7 @@ kFujitsuAcTempOffsetC LITERAL1 kFujitsuAcTempOffsetF LITERAL1 kFujitsuAcTimerMax LITERAL1 kFujitsuAcZeroSpace LITERAL1 +kGe6711ar2853mStr LITERAL1 kGicableBitMark LITERAL1 kGicableBits LITERAL1 kGicableHdrMark LITERAL1 @@ -2146,6 +2238,13 @@ kGreeStateLength LITERAL1 kGreeSwingAuto LITERAL1 kGreeSwingDown LITERAL1 kGreeSwingDownAuto LITERAL1 +kGreeSwingHAuto LITERAL1 +kGreeSwingHLeft LITERAL1 +kGreeSwingHMaxLeft LITERAL1 +kGreeSwingHMaxRight LITERAL1 +kGreeSwingHMiddle LITERAL1 +kGreeSwingHOff LITERAL1 +kGreeSwingHRight LITERAL1 kGreeSwingLastPos LITERAL1 kGreeSwingMiddle LITERAL1 kGreeSwingMiddleAuto LITERAL1 @@ -2155,6 +2254,7 @@ kGreeSwingUp LITERAL1 kGreeSwingUpAuto LITERAL1 kGreeTimerMax LITERAL1 kGreeZeroSpace LITERAL1 +kGz055be1Str LITERAL1 kHaierAC176Bits LITERAL1 kHaierAC176StateLength LITERAL1 kHaierACBits LITERAL1 @@ -2195,21 +2295,26 @@ kHaierAcMinTemp LITERAL1 kHaierAcOneSpace LITERAL1 kHaierAcPrefix LITERAL1 kHaierAcSleepBit LITERAL1 -kHaierAcSwingChg LITERAL1 -kHaierAcSwingDown LITERAL1 -kHaierAcSwingOff LITERAL1 -kHaierAcSwingUp LITERAL1 +kHaierAcSwingVChg LITERAL1 +kHaierAcSwingVDown LITERAL1 +kHaierAcSwingVOff LITERAL1 +kHaierAcSwingVUp LITERAL1 kHaierAcYrw02Auto LITERAL1 +kHaierAcYrw02ButtonCFAB LITERAL1 kHaierAcYrw02ButtonFan LITERAL1 kHaierAcYrw02ButtonHealth LITERAL1 +kHaierAcYrw02ButtonLock LITERAL1 kHaierAcYrw02ButtonMode LITERAL1 kHaierAcYrw02ButtonPower LITERAL1 kHaierAcYrw02ButtonSleep LITERAL1 -kHaierAcYrw02ButtonSwing LITERAL1 +kHaierAcYrw02ButtonSwingH LITERAL1 +kHaierAcYrw02ButtonSwingV LITERAL1 kHaierAcYrw02ButtonTempDown LITERAL1 kHaierAcYrw02ButtonTempUp LITERAL1 +kHaierAcYrw02ButtonTimer LITERAL1 kHaierAcYrw02ButtonTurbo LITERAL1 kHaierAcYrw02Cool LITERAL1 +kHaierAcYrw02DefTempC LITERAL1 kHaierAcYrw02DefaultRepeat LITERAL1 kHaierAcYrw02Dry LITERAL1 kHaierAcYrw02Fan LITERAL1 @@ -2218,26 +2323,35 @@ kHaierAcYrw02FanHigh LITERAL1 kHaierAcYrw02FanLow LITERAL1 kHaierAcYrw02FanMed LITERAL1 kHaierAcYrw02Heat LITERAL1 +kHaierAcYrw02MaxTempC LITERAL1 +kHaierAcYrw02MaxTempF LITERAL1 +kHaierAcYrw02MinTempC LITERAL1 +kHaierAcYrw02MinTempF LITERAL1 +kHaierAcYrw02ModelA LITERAL1 +kHaierAcYrw02ModelB LITERAL1 kHaierAcYrw02NoTimers LITERAL1 kHaierAcYrw02OffThenOnTimer LITERAL1 kHaierAcYrw02OffTimer LITERAL1 kHaierAcYrw02OnThenOffTimer LITERAL1 kHaierAcYrw02OnTimer LITERAL1 -kHaierAcYrw02Prefix LITERAL1 -kHaierAcYrw02SwingAuto LITERAL1 -kHaierAcYrw02SwingBottom LITERAL1 -kHaierAcYrw02SwingDown LITERAL1 -kHaierAcYrw02SwingMiddle LITERAL1 -kHaierAcYrw02SwingOff LITERAL1 -kHaierAcYrw02SwingTop LITERAL1 -kHaierAcYrw02TurboHigh LITERAL1 -kHaierAcYrw02TurboLow LITERAL1 -kHaierAcYrw02TurboOff LITERAL1 +kHaierAcYrw02SwingHAuto LITERAL1 +kHaierAcYrw02SwingHLeft LITERAL1 +kHaierAcYrw02SwingHLeftMax LITERAL1 +kHaierAcYrw02SwingHMiddle LITERAL1 +kHaierAcYrw02SwingHRight LITERAL1 +kHaierAcYrw02SwingHRightMax LITERAL1 +kHaierAcYrw02SwingVAuto LITERAL1 +kHaierAcYrw02SwingVBottom LITERAL1 +kHaierAcYrw02SwingVDown LITERAL1 +kHaierAcYrw02SwingVMiddle LITERAL1 +kHaierAcYrw02SwingVOff LITERAL1 +kHaierAcYrw02SwingVTop LITERAL1 kHaierAcZeroSpace LITERAL1 kHeader LITERAL1 kHealthStr LITERAL1 kHeat LITERAL1 kHeatStr LITERAL1 +kHeatingStr LITERAL1 kHiStr LITERAL1 kHigh LITERAL1 kHighNibble LITERAL1 @@ -2377,6 +2491,7 @@ kInaxTick LITERAL1 kInaxZeroSpace LITERAL1 kInsideStr LITERAL1 kIonStr LITERAL1 +kJkeStr LITERAL1 kJvcBitMark LITERAL1 kJvcBitMarkTicks LITERAL1 kJvcBits LITERAL1 @@ -2445,6 +2560,8 @@ kKelvinatorStateLength LITERAL1 kKelvinatorTick LITERAL1 kKelvinatorZeroSpace LITERAL1 kKelvinatorZeroSpaceTicks LITERAL1 +kKkg29ac1Str LITERAL1 +kKkg9ac1Str LITERAL1 kLasertagBits LITERAL1 kLasertagDelta LITERAL1 kLasertagExcess LITERAL1 @@ -2461,6 +2578,7 @@ kLastSwinghEnum LITERAL1 kLastSwingvEnum LITERAL1 kLeft LITERAL1 kLeftMax LITERAL1 +kLeftMaxNoSpaceStr LITERAL1 kLeftMaxStr LITERAL1 kLeftStr LITERAL1 kLegoPfBitMark LITERAL1 @@ -2544,7 +2662,9 @@ kLgRptSpace LITERAL1 kLgZeroSpace LITERAL1 kLightStr LITERAL1 kLightToggleStr LITERAL1 +kLkeStr LITERAL1 kLoStr LITERAL1 +kLockStr LITERAL1 kLoudStr LITERAL1 kLow LITERAL1 kLowNibble LITERAL1 @@ -2578,7 +2698,9 @@ kMarkExcess LITERAL1 kMarkState LITERAL1 kMax LITERAL1 kMaxAccurateUsecDelay LITERAL1 +kMaxLeftNoSpaceStr LITERAL1 kMaxLeftStr LITERAL1 +kMaxRightNoSpaceStr LITERAL1 kMaxRightStr LITERAL1 kMaxStr LITERAL1 kMaxTimeoutMs LITERAL1 @@ -2661,6 +2783,34 @@ kMinStr LITERAL1 kMinimumStr LITERAL1 kMinuteStr LITERAL1 kMinutesStr LITERAL1 +kMirageAcCool LITERAL1 +kMirageAcDry LITERAL1 +kMirageAcFan LITERAL1 +kMirageAcFanAuto LITERAL1 +kMirageAcFanHigh LITERAL1 +kMirageAcFanLow LITERAL1 +kMirageAcFanMed LITERAL1 +kMirageAcHeat LITERAL1 +kMirageAcKKG29AC1FanAuto LITERAL1 +kMirageAcKKG29AC1FanHigh LITERAL1 +kMirageAcKKG29AC1FanLow LITERAL1 +kMirageAcKKG29AC1FanMed LITERAL1 +kMirageAcKKG29AC1PowerOff LITERAL1 +kMirageAcKKG29AC1PowerOn LITERAL1 +kMirageAcMaxTemp LITERAL1 +kMirageAcMinTemp LITERAL1 +kMirageAcPowerOff LITERAL1 +kMirageAcRecycle LITERAL1 +kMirageAcSensorTempMax LITERAL1 +kMirageAcSensorTempOffset LITERAL1 +kMirageAcSwingVAuto LITERAL1 +kMirageAcSwingVHigh LITERAL1 +kMirageAcSwingVHighest LITERAL1 +kMirageAcSwingVLow LITERAL1 +kMirageAcSwingVLowest LITERAL1 +kMirageAcSwingVMiddle LITERAL1 +kMirageAcSwingVOff LITERAL1 +kMirageAcTempOffset LITERAL1 kMirageBitMark LITERAL1 kMirageBits LITERAL1 kMirageFreq LITERAL1 @@ -2954,6 +3104,7 @@ kNikaiOneSpaceTicks LITERAL1 kNikaiTick LITERAL1 kNikaiZeroSpace LITERAL1 kNikaiZeroSpaceTicks LITERAL1 +kNkeStr LITERAL1 kNoRepeat LITERAL1 kNoStr LITERAL1 kNowStr LITERAL1 @@ -3042,20 +3193,27 @@ kPanasonicAcTolerance LITERAL1 kPanasonicBitMark LITERAL1 kPanasonicBits LITERAL1 kPanasonicCkp LITERAL1 +kPanasonicCkpStr LITERAL1 kPanasonicDke LITERAL1 +kPanasonicDkeStr LITERAL1 kPanasonicEndGap LITERAL1 kPanasonicFreq LITERAL1 kPanasonicHdrMark LITERAL1 kPanasonicHdrSpace LITERAL1 kPanasonicJke LITERAL1 +kPanasonicJkeStr LITERAL1 kPanasonicKnownGoodState LITERAL1 kPanasonicLke LITERAL1 +kPanasonicLkeStr LITERAL1 kPanasonicManufacturer LITERAL1 kPanasonicMinCommandLength LITERAL1 kPanasonicMinGap LITERAL1 kPanasonicNke LITERAL1 +kPanasonicNkeStr LITERAL1 kPanasonicOneSpace LITERAL1 +kPanasonicPkrStr LITERAL1 kPanasonicRkr LITERAL1 +kPanasonicRkrStr LITERAL1 kPanasonicUnknown LITERAL1 kPanasonicZeroSpace LITERAL1 kPeriodOffset LITERAL1 @@ -3068,6 +3226,7 @@ kPioneerMinGap LITERAL1 kPioneerOneSpace LITERAL1 kPioneerTick LITERAL1 kPioneerZeroSpace LITERAL1 +kPkrStr LITERAL1 kPowerButtonStr LITERAL1 kPowerStr LITERAL1 kPowerToggleStr LITERAL1 @@ -3145,10 +3304,44 @@ kRcz01SignatureMask LITERAL1 kRecycleStr LITERAL1 kRepeat LITERAL1 kRepeatStr LITERAL1 +kRhossBitMark LITERAL1 +kRhossBits LITERAL1 +kRhossDefaultFan LITERAL1 +kRhossDefaultMode LITERAL1 +kRhossDefaultPower LITERAL1 +kRhossDefaultRepeat LITERAL1 +kRhossDefaultSwing LITERAL1 +kRhossDefaultTemp LITERAL1 +kRhossFanAuto LITERAL1 +kRhossFanMax LITERAL1 +kRhossFanMed LITERAL1 +kRhossFanMin LITERAL1 +kRhossFreq LITERAL1 +kRhossGap LITERAL1 +kRhossHdrMark LITERAL1 +kRhossHdrSpace LITERAL1 +kRhossModeAuto LITERAL1 +kRhossModeCool LITERAL1 +kRhossModeDry LITERAL1 +kRhossModeFan LITERAL1 +kRhossModeHeat LITERAL1 +kRhossOneSpace LITERAL1 +kRhossPowerOff LITERAL1 +kRhossPowerOn LITERAL1 +kRhossStateLength LITERAL1 +kRhossSwingOff LITERAL1 +kRhossSwingOn LITERAL1 +kRhossTempMax LITERAL1 +kRhossTempMin LITERAL1 +kRhossZeroSpace LITERAL1 kRight LITERAL1 kRightMax LITERAL1 +kRightMaxNoSpaceStr LITERAL1 kRightMaxStr LITERAL1 kRightStr LITERAL1 +kRkrStr LITERAL1 +kRlt0541htaaStr LITERAL1 +kRlt0541htabStr LITERAL1 kRoomStr LITERAL1 kSamsung36BitMark LITERAL1 kSamsung36Bits LITERAL1 @@ -3164,6 +3357,7 @@ kSamsungAcBreezeOn LITERAL1 kSamsungAcCool LITERAL1 kSamsungAcDefaultRepeat LITERAL1 kSamsungAcDry LITERAL1 +kSamsungAcEconoOn LITERAL1 kSamsungAcExtendedBits LITERAL1 kSamsungAcExtendedStateLength LITERAL1 kSamsungAcFan LITERAL1 @@ -3172,6 +3366,7 @@ kSamsungAcFanAuto2 LITERAL1 kSamsungAcFanHigh LITERAL1 kSamsungAcFanLow LITERAL1 kSamsungAcFanMed LITERAL1 +kSamsungAcFanSpecialOff LITERAL1 kSamsungAcFanTurbo LITERAL1 kSamsungAcHdrMark LITERAL1 kSamsungAcHdrSpace LITERAL1 @@ -3180,16 +3375,17 @@ kSamsungAcMaxTemp LITERAL1 kSamsungAcMinTemp LITERAL1 kSamsungAcOneSpace LITERAL1 kSamsungAcPowerSection LITERAL1 -kSamsungAcPowerful10On LITERAL1 -kSamsungAcPowerfulMask8 LITERAL1 +kSamsungAcPowerfulOn LITERAL1 kSamsungAcSectionGap LITERAL1 kSamsungAcSectionLength LITERAL1 kSamsungAcSectionMark LITERAL1 kSamsungAcSectionSpace LITERAL1 kSamsungAcSections LITERAL1 kSamsungAcStateLength LITERAL1 -kSamsungAcSwingMove LITERAL1 -kSamsungAcSwingStop LITERAL1 +kSamsungAcSwingBoth LITERAL1 +kSamsungAcSwingH LITERAL1 +kSamsungAcSwingOff LITERAL1 +kSamsungAcSwingV LITERAL1 kSamsungAcZeroSpace LITERAL1 kSamsungBitMark LITERAL1 kSamsungBitMarkTicks LITERAL1 @@ -3326,8 +3522,15 @@ kSharpAcSpecialTimer LITERAL1 kSharpAcSpecialTimerHalfHour LITERAL1 kSharpAcSpecialTurbo LITERAL1 kSharpAcStateLength LITERAL1 -kSharpAcSwingNoToggle LITERAL1 -kSharpAcSwingToggle LITERAL1 +kSharpAcSwingVCoanda LITERAL1 +kSharpAcSwingVHigh LITERAL1 +kSharpAcSwingVIgnore LITERAL1 +kSharpAcSwingVLast LITERAL1 +kSharpAcSwingVLow LITERAL1 +kSharpAcSwingVLowest LITERAL1 +kSharpAcSwingVMid LITERAL1 +kSharpAcSwingVOff LITERAL1 +kSharpAcSwingVToggle LITERAL1 kSharpAcTimerHoursMax LITERAL1 kSharpAcTimerHoursOff LITERAL1 kSharpAcTimerIncrement LITERAL1 @@ -3397,6 +3600,7 @@ kSymphonyOneMark LITERAL1 kSymphonyOneSpace LITERAL1 kSymphonyZeroMark LITERAL1 kSymphonyZeroSpace LITERAL1 +kTac09chsdStr LITERAL1 kTcl112AcAuto LITERAL1 kTcl112AcBitMark LITERAL1 kTcl112AcBits LITERAL1 @@ -3408,6 +3612,9 @@ kTcl112AcFanAuto LITERAL1 kTcl112AcFanHigh LITERAL1 kTcl112AcFanLow LITERAL1 kTcl112AcFanMed LITERAL1 +kTcl112AcFanMin LITERAL1 +kTcl112AcFanNight LITERAL1 +kTcl112AcFanQuiet LITERAL1 kTcl112AcGap LITERAL1 kTcl112AcHdrMark LITERAL1 kTcl112AcHdrMarkTolerance LITERAL1 @@ -3417,10 +3624,17 @@ kTcl112AcNormal LITERAL1 kTcl112AcOneSpace LITERAL1 kTcl112AcSpecial LITERAL1 kTcl112AcStateLength LITERAL1 +kTcl112AcSwingVHigh LITERAL1 +kTcl112AcSwingVHighest LITERAL1 +kTcl112AcSwingVLow LITERAL1 +kTcl112AcSwingVLowest LITERAL1 +kTcl112AcSwingVMiddle LITERAL1 kTcl112AcSwingVOff LITERAL1 kTcl112AcSwingVOn LITERAL1 kTcl112AcTempMax LITERAL1 kTcl112AcTempMin LITERAL1 +kTcl112AcTimerMax LITERAL1 +kTcl112AcTimerResolution LITERAL1 kTcl112AcTolerance LITERAL1 kTcl112AcZeroSpace LITERAL1 kTechnibelAcBitMark LITERAL1 @@ -3482,6 +3696,7 @@ kTempDownStr LITERAL1 kTempStr LITERAL1 kTempUpStr LITERAL1 kThreeLetterDayOfWeekStr LITERAL1 +kTimeSep LITERAL1 kTimeoutMs LITERAL1 kTimerModeStr LITERAL1 kTimerStr LITERAL1 @@ -3617,6 +3832,8 @@ kUnknownThreshold LITERAL1 kUpStr LITERAL1 kUpperStr LITERAL1 kUseDefTol LITERAL1 +kV9014557AStr LITERAL1 +kV9014557BStr LITERAL1 kVaneStr LITERAL1 kVestelAcAuto LITERAL1 kVestelAcBitMark LITERAL1 @@ -3737,6 +3954,8 @@ kXmpRepeatCodeAlt LITERAL1 kXmpSections LITERAL1 kXmpSpaceStep LITERAL1 kXmpWordSize LITERAL1 +kYaw1fStr LITERAL1 +kYbofbStr LITERAL1 kYesStr LITERAL1 kZepealBits LITERAL1 kZepealCommandOffOn LITERAL1 diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/library.json b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/library.json index 5bce2238e..99160ec37 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/library.json +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/library.json @@ -1,6 +1,6 @@ { "name": "IRremoteESP8266", - "version": "2.7.20", + "version": "2.8.0", "keywords": "infrared, ir, remote, esp8266, esp32", "description": "Send and receive infrared signals with multiple protocols (ESP8266/ESP32)", "repository": diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/library.properties b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/library.properties index e4985e2a2..e7580dd2d 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/library.properties +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/library.properties @@ -1,5 +1,5 @@ name=IRremoteESP8266 -version=2.7.20 +version=2.8.0 author=David Conran, Sebastien Warin, Mark Szabo, Ken Shirriff maintainer=David Conran, Mark Szabo, Sebastien Warin, Roi Dayan, Massimiliano Pinto, Christian Nilsson sentence=Send and receive infrared signals with multiple protocols (ESP8266/ESP32) diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRac.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRac.cpp index 9b4e10cbd..557e5593e 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRac.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRac.cpp @@ -36,6 +36,7 @@ #include "ir_MitsubishiHeavy.h" #include "ir_Neoclima.h" #include "ir_Panasonic.h" +#include "ir_Rhoss.h" #include "ir_Samsung.h" #include "ir_Sanyo.h" #include "ir_Sharp.h" @@ -50,6 +51,17 @@ #include "ir_Voltas.h" #include "ir_Whirlpool.h" +// On the ESP8266 platform we need to use a special version of string handling +// functions to handle the strings stored in the flash address space. +#ifndef STRCASECMP +#if defined(ESP8266) +#define STRCASECMP(LHS, RHS) \ + strcasecmp_P(LHS, reinterpret_cast(RHS)) +#else // ESP8266 +#define STRCASECMP(LHS, RHS) strcasecmp(LHS, RHS) +#endif // ESP8266 +#endif // STRCASECMP + /// Class constructor /// @param[in] pin Gpio pin to use when transmitting IR messages. /// @param[in] inverted true, gpio output defaults to high. false, to low. @@ -233,7 +245,10 @@ bool IRac::isProtocolSupported(const decode_type_t protocol) { #endif #if SEND_MIDEA case decode_type_t::MIDEA: -#endif +#endif // SEND_MIDEA +#if SEND_MIRAGE + case decode_type_t::MIRAGE: +#endif // SEND_MIRAGE #if SEND_MITSUBISHI_AC case decode_type_t::MITSUBISHI_AC: #endif @@ -256,6 +271,9 @@ bool IRac::isProtocolSupported(const decode_type_t protocol) { #if SEND_PANASONIC_AC32 case decode_type_t::PANASONIC_AC32: #endif +#if SEND_RHOSS + case decode_type_t::RHOSS: +#endif #if SEND_SAMSUNG_AC case decode_type_t::SAMSUNG_AC: #endif @@ -277,6 +295,9 @@ bool IRac::isProtocolSupported(const decode_type_t protocol) { #if SEND_TECO case decode_type_t::TECO: #endif +#if SEND_TEKNOPOINT + case decode_type_t::TEKNOPOINT: +#endif // SEND_TEKNOPOINT #if SEND_TOSHIBA_AC case decode_type_t::TOSHIBA_AC: #endif @@ -1018,15 +1039,18 @@ void IRac::goodweather(IRGoodweatherAc *ac, /// @param[in] degrees The temperature setting in degrees. /// @param[in] fan The speed setting for the fan. /// @param[in] swingv The vertical swing setting. +/// @param[in] swingh The horizontal swing setting. /// @param[in] turbo Run the device in turbo/powerful mode. +/// @param[in] econo Toggle the device's economical mode. /// @param[in] light Turn on the LED/Display mode. /// @param[in] clean Turn on the self-cleaning mode. e.g. Mould, dry filters etc /// @param[in] sleep Nr. of minutes for sleep mode. -1 is Off, >= 0 is on. void IRac::gree(IRGreeAC *ac, const gree_ac_remote_model_t model, const bool on, const stdAc::opmode_t mode, const bool celsius, const float degrees, const stdAc::fanspeed_t fan, - const stdAc::swingv_t swingv, const bool turbo, - const bool light, const bool clean, const int16_t sleep) { + const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, + const bool turbo, const bool econo, const bool light, + const bool clean, const int16_t sleep) { ac->begin(); ac->setModel(model); ac->setPower(on); @@ -1035,11 +1059,12 @@ void IRac::gree(IRGreeAC *ac, const gree_ac_remote_model_t model, ac->setFan(ac->convertFan(fan)); ac->setSwingVertical(swingv == stdAc::swingv_t::kAuto, // Set auto flag. ac->convertSwingV(swingv)); + ac->setSwingHorizontal(ac->convertSwingH(swingh)); ac->setLight(light); ac->setTurbo(turbo); + ac->setEcono(econo); ac->setXFan(clean); ac->setSleep(sleep >= 0); // Sleep on this A/C is either on or off. - // No Horizontal Swing setting available. // No Econo setting available. // No Filter setting available. // No Beep setting available. @@ -1068,7 +1093,7 @@ void IRac::haier(IRHaierAC *ac, ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); - ac->setSwing(ac->convertSwingV(swingv)); + ac->setSwingV(ac->convertSwingV(swingv)); // No Horizontal Swing setting available. // No Quiet setting available. // No Turbo setting available. @@ -1089,26 +1114,35 @@ void IRac::haier(IRHaierAC *ac, #if SEND_HAIER_AC176 /// Send a Haier 176 bit A/C message with the supplied settings. /// @param[in, out] ac A Ptr to an IRHaierAC176 object to use. +/// @param[in] model The A/C model to use. /// @param[in] on The power setting. /// @param[in] mode The operation mode setting. +/// @param[in] celsius Temperature units. True is Celsius, False is Fahrenheit. /// @param[in] degrees The temperature setting in degrees. /// @param[in] fan The speed setting for the fan. /// @param[in] swingv The vertical swing setting. +/// @param[in] swingh The horizontal swing setting. /// @param[in] turbo Run the device in turbo/powerful mode. +/// @param[in] quiet Run the device in quiet mode. /// @param[in] filter Turn on the (ion/pollen/etc) filter mode. /// @param[in] sleep Nr. of minutes for sleep mode. -1 is Off, >= 0 is on. -void IRac::haier176(IRHaierAC176 *ac, +void IRac::haier176(IRHaierAC176 *ac, const haier_ac176_remote_model_t model, const bool on, const stdAc::opmode_t mode, - const float degrees, const stdAc::fanspeed_t fan, - const stdAc::swingv_t swingv, const bool turbo, - const bool filter, const int16_t sleep) { + const bool celsius, const float degrees, + const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, + const stdAc::swingh_t swingh, + const bool turbo, const bool quiet, const bool filter, + const int16_t sleep) { ac->begin(); + ac->setModel(model); ac->setMode(ac->convertMode(mode)); + ac->setUseFahrenheit(!celsius); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); - ac->setSwing(ac->convertSwingV(swingv)); - // No Horizontal Swing setting available. - // No Quiet setting available. + ac->setSwingV(ac->convertSwingV(swingv)); + ac->setSwingH(ac->convertSwingH(swingh)); + ac->setQuiet(quiet); ac->setTurbo(turbo); // No Light setting available. ac->setHealth(filter); @@ -1125,24 +1159,31 @@ void IRac::haier176(IRHaierAC176 *ac, /// @param[in, out] ac A Ptr to an IRHaierACYRW02 object to use. /// @param[in] on The power setting. /// @param[in] mode The operation mode setting. +/// @param[in] celsius Temperature units. True is Celsius, False is Fahrenheit. /// @param[in] degrees The temperature setting in degrees. /// @param[in] fan The speed setting for the fan. /// @param[in] swingv The vertical swing setting. +/// @param[in] swingh The horizontal swing setting. /// @param[in] turbo Run the device in turbo/powerful mode. +/// @param[in] quiet Run the device in quiet mode. /// @param[in] filter Turn on the (ion/pollen/etc) filter mode. /// @param[in] sleep Nr. of minutes for sleep mode. -1 is Off, >= 0 is on. void IRac::haierYrwo2(IRHaierACYRW02 *ac, const bool on, const stdAc::opmode_t mode, - const float degrees, const stdAc::fanspeed_t fan, - const stdAc::swingv_t swingv, const bool turbo, - const bool filter, const int16_t sleep) { + const bool celsius, const float degrees, + const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, + const stdAc::swingh_t swingh, + const bool turbo, const bool quiet, const bool filter, + const int16_t sleep) { ac->begin(); ac->setMode(ac->convertMode(mode)); + ac->setUseFahrenheit(!celsius); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); - ac->setSwing(ac->convertSwingV(swingv)); - // No Horizontal Swing setting available. - // No Quiet setting available. + ac->setSwingV(ac->convertSwingV(swingv)); + ac->setSwingH(ac->convertSwingH(swingh)); + ac->setQuiet(quiet); ac->setTurbo(turbo); // No Light setting available. ac->setHealth(filter); @@ -1450,6 +1491,17 @@ void IRac::midea(IRMideaAC *ac, } #endif // SEND_MIDEA +#if SEND_MIRAGE +/// Send a Mirage 120-bit A/C message with the supplied settings. +/// @param[in, out] ac A Ptr to an IRMitsubishiAC object to use. +/// @param[in] state The desired state to send. +void IRac::mirage(IRMirageAc *ac, const stdAc::state_t state) { + ac->begin(); + ac->fromCommon(state); + ac->send(); +} +#endif // SEND_MIRAGE + #if SEND_MITSUBISHI_AC /// Send a Mitsubishi A/C message with the supplied settings. /// @param[in, out] ac A Ptr to an IRMitsubishiAC object to use. @@ -1766,38 +1818,45 @@ void IRac::panasonic32(IRPanasonicAc32 *ac, /// @param[in] degrees The temperature setting in degrees. /// @param[in] fan The speed setting for the fan. /// @param[in] swingv The vertical swing setting. +/// @param[in] swingh The horizontal swing setting. /// @param[in] quiet Run the device in quiet/silent mode. /// @param[in] turbo Run the device in turbo/powerful mode. +/// @param[in] econo Run the device in economical mode. /// @param[in] light Turn on the LED/Display mode. /// @param[in] filter Turn on the (ion/pollen/etc) filter mode. -/// @param[in] clean Turn on the self-cleaning mode. e.g. Mould, dry filters etc -/// @param[in] beep Enable/Disable beeps when receiving IR messages. +/// @param[in] clean Toggle the self-cleaning mode. e.g. Mould, dry filters etc +/// @param[in] beep Toggle beep setting for receiving IR messages. +/// @param[in] sleep Nr. of minutes for sleep mode. <= 0 is Off, > 0 is on. /// @param[in] prevpower The power setting from the previous A/C state. -/// @param[in] forcepower Do we force send the special power message? +/// @param[in] prevsleep Nr. of minutes for sleep from the previous A/C state. +/// @param[in] forceextended Do we force sending the special extended message? void IRac::samsung(IRSamsungAc *ac, const bool on, const stdAc::opmode_t mode, const float degrees, - const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, - const bool quiet, const bool turbo, const bool light, + const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, + const bool quiet, const bool turbo, const bool econo, + const bool light, const bool filter, const bool clean, - const bool beep, const bool prevpower, - const bool forcepower) { + const bool beep, const int16_t sleep, + const bool prevpower, const int16_t prevsleep, + const bool forceextended) { ac->begin(); - ac->stateReset(forcepower, prevpower); + ac->stateReset(forceextended || (sleep != prevsleep), prevpower); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); ac->setSwing(swingv != stdAc::swingv_t::kOff); - // No Horizontal swing setting available. + ac->setSwingH(swingh != stdAc::swingh_t::kOff); ac->setQuiet(quiet); - ac->setPowerful(turbo); + ac->setPowerful(turbo); // FYI, `setEcono(true)` will override this. ac->setDisplay(light); - // No Econo setting available. + ac->setEcono(econo); ac->setIon(filter); - ac->setClean(clean); - ac->setBeep(beep); - // No Sleep setting available. + ac->setClean(clean); // Toggle + ac->setBeep(beep); // Toggle + ac->setSleepTimer((sleep <= 0) ? 0 : sleep); // No Clock setting available. // Do setMode() again as it can affect fan speed. ac->setMode(ac->convertMode(mode)); @@ -1893,6 +1952,7 @@ void IRac::sanyo88(IRSanyoAc88 *ac, /// @param[in] degrees The temperature setting in degrees. /// @param[in] fan The speed setting for the fan. /// @param[in] swingv The vertical swing setting. +/// @param[in] swingv_prev The previous vertical swing setting. /// @param[in] turbo Run the device in turbo/powerful mode. /// @param[in] light Turn on the LED/Display mode. /// @param[in] filter Turn on the (ion/pollen/etc) filter mode. @@ -1901,14 +1961,15 @@ void IRac::sharp(IRSharpAc *ac, const sharp_ac_remote_model_t model, const bool on, const bool prev_power, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, - const stdAc::swingv_t swingv, const bool turbo, + const stdAc::swingv_t swingv, + const stdAc::swingv_t swingv_prev, const bool turbo, const bool light, const bool filter, const bool clean) { ac->begin(); ac->setModel(model); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan, model)); - ac->setSwingToggle(swingv != stdAc::swingv_t::kOff); + if (swingv != swingv_prev) ac->setSwingV(ac->convertSwingV(swingv)); // Econo deliberately not used as it cycles through 3 modes uncontrollably. // ac->setEconoToggle(econo); ac->setIon(filter); @@ -1940,6 +2001,7 @@ void IRac::sharp(IRSharpAc *ac, const sharp_ac_remote_model_t model, #if SEND_TCL112AC /// Send a TCL 112-bit A/C message with the supplied settings. /// @param[in, out] ac A Ptr to an IRTcl112Ac object to use. +/// @param[in] model The A/C model to use. /// @param[in] on The power setting. /// @param[in] mode The operation mode setting. /// @param[in] degrees The temperature setting in degrees. @@ -1951,18 +2013,19 @@ void IRac::sharp(IRSharpAc *ac, const sharp_ac_remote_model_t model, /// @param[in] light Turn on the LED/Display mode. /// @param[in] econo Run the device in economical mode. /// @param[in] filter Turn on the (ion/pollen/etc) filter mode. -void IRac::tcl112(IRTcl112Ac *ac, +void IRac::tcl112(IRTcl112Ac *ac, const tcl_ac_remote_model_t model, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, const bool quiet, const bool turbo, const bool light, const bool econo, const bool filter) { ac->begin(); + ac->setModel(model); ac->setPower(on); ac->setMode(ac->convertMode(mode)); ac->setTemp(degrees); ac->setFan(ac->convertFan(fan)); - ac->setSwingVertical(swingv != stdAc::swingv_t::kOff); + ac->setSwingVertical(ac->convertSwingV(swingv)); ac->setSwingHorizontal(swingh != stdAc::swingh_t::kOff); ac->setQuiet(quiet); ac->setTurbo(turbo); @@ -2341,6 +2404,35 @@ void IRac::transcold(IRTranscoldAc *ac, } #endif // SEND_TRANSCOLD +#if SEND_RHOSS +/// Send an Rhoss A/C message with the supplied settings. +/// @param[in, out] ac A Ptr to an IRRhossAc object to use. +/// @param[in] on The power setting. +/// @param[in] mode The operation mode setting. +/// @param[in] degrees The temperature setting in degrees. +/// @param[in] fan The speed setting for the fan. +/// @param[in] swing The swing setting. +void IRac::rhoss(IRRhossAc *ac, + const bool on, const stdAc::opmode_t mode, const float degrees, + const stdAc::fanspeed_t fan, const stdAc::swingv_t swing) { + ac->begin(); + ac->setPower(on); + ac->setMode(ac->convertMode(mode)); + ac->setSwing(swing != stdAc::swingv_t::kOff); + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + // No Quiet setting available. + // No Light setting available. + // No Filter setting available. + // No Turbo setting available. + // No Economy setting available. + // No Clean setting available. + // No Beep setting available. + // No Sleep setting available. + ac->send(); +} +#endif // SEND_RHOSS + /// Create a new state base on the provided state that has been suitably fixed. /// @note This is for use with Home Assistant, which requires mode to be off if /// the power is off. @@ -2425,11 +2517,20 @@ stdAc::state_t IRac::handleToggles(const stdAc::state_t desired, case decode_type_t::WHIRLPOOL_AC: result.power = desired.power ^ prev->power; break; + case decode_type_t::MIRAGE: + if (desired.model == mirage_ac_remote_model_t::KKG29AC1) + result.light = desired.light ^ prev->light; + result.clean = desired.clean ^ prev->clean; + break; case decode_type_t::PANASONIC_AC: // CKP models use a power mode toggle. if (desired.model == panasonic_ac_remote_model_t::kPanasonicCkp) result.power = desired.power ^ prev->power; break; + case decode_type_t::SAMSUNG_AC: + result.beep = desired.beep ^ prev->beep; + result.clean = desired.clean ^ prev->clean; + break; default: {}; } @@ -2494,11 +2595,12 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) { // Construct a pointer-safe previous power state incase prev is NULL/NULLPTR. #if (SEND_HITACHI_AC1 || SEND_SAMSUNG_AC || SEND_SHARP_AC) const bool prev_power = (prev != NULL) ? prev->power : !send.power; + const int16_t prev_sleep = (prev != NULL) ? prev->sleep : -1; #endif // (SEND_HITACHI_AC1 || SEND_SAMSUNG_AC || SEND_SHARP_AC) -#if SEND_LG +#if (SEND_LG || SEND_SHARP_AC) const stdAc::swingv_t prev_swingv = (prev != NULL) ? prev->swingv : stdAc::swingv_t::kOff; -#endif // SEND_LG +#endif // (SEND_LG || SEND_SHARP_AC) // Per vendor settings & setup. switch (send.protocol) { #if SEND_AIRWELL @@ -2678,8 +2780,8 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) { IRGreeAC ac(_pin, (gree_ac_remote_model_t)send.model, _inverted, _modulation); gree(&ac, (gree_ac_remote_model_t)send.model, send.power, send.mode, - send.celsius, send.degrees, send.fanspeed, send.swingv, send.turbo, - send.light, send.clean, send.sleep); + send.celsius, send.degrees, send.fanspeed, send.swingv, send.swingh, + send.turbo, send.econo, send.light, send.clean, send.sleep); break; } #endif // SEND_GREE @@ -2696,8 +2798,9 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) { case HAIER_AC176: { IRHaierAC176 ac(_pin, _inverted, _modulation); - haier176(&ac, send.power, send.mode, degC, send.fanspeed, send.swingv, - send.turbo, send.filter, send.sleep); + haier176(&ac, (haier_ac176_remote_model_t)send.model, send.power, + send.mode, send.celsius, send.degrees, send.fanspeed, + send.swingv, send.swingh, send.turbo, send.filter, send.sleep); break; } #endif // SEND_HAIER_AC176 @@ -2705,8 +2808,9 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) { case HAIER_AC_YRW02: { IRHaierACYRW02 ac(_pin, _inverted, _modulation); - haierYrwo2(&ac, send.power, send.mode, degC, send.fanspeed, send.swingv, - send.turbo, send.filter, send.sleep); + haierYrwo2(&ac, send.power, send.mode, send.celsius, send.degrees, + send.fanspeed, send.swingv, send.swingh, send.turbo, + send.filter, send.sleep); break; } #endif // SEND_HAIER_AC_YRW02 @@ -2792,6 +2896,14 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) { break; } #endif // SEND_MIDEA +#if SEND_MIRAGE + case MIRAGE: + { + IRMirageAc ac(_pin, _inverted, _modulation); + mirage(&ac, send); + break; + } +#endif // SEND_MIRAGE #if SEND_MITSUBISHI_AC case MITSUBISHI_AC: { @@ -2866,13 +2978,22 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) { break; } #endif // SEND_PANASONIC_AC32 +#if SEND_RHOSS + case RHOSS: + { + IRRhossAc ac(_pin, _inverted, _modulation); + rhoss(&ac, send.power, send.mode, degC, send.fanspeed, send.swingv); + break; + } +#endif // SEND_RHOSS #if SEND_SAMSUNG_AC case SAMSUNG_AC: { IRSamsungAc ac(_pin, _inverted, _modulation); samsung(&ac, send.power, send.mode, degC, send.fanspeed, send.swingv, - send.quiet, send.turbo, send.light, send.filter, send.clean, - send.beep, prev_power); + send.swingh, send.quiet, send.turbo, send.econo, send.light, + send.filter, send.clean, send.beep, send.sleep, + prev_power, prev_sleep); break; } #endif // SEND_SAMSUNG_AC @@ -2899,21 +3020,25 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) { { IRSharpAc ac(_pin, _inverted, _modulation); sharp(&ac, (sharp_ac_remote_model_t)send.model, send.power, prev_power, - send.mode, degC, send.fanspeed, send.swingv, send.turbo, send.light, - send.filter, send.clean); + send.mode, degC, send.fanspeed, send.swingv, prev_swingv, + send.turbo, send.light, send.filter, send.clean); break; } #endif // SEND_SHARP_AC -#if SEND_TCL112AC +#if (SEND_TCL112AC || SEND_TEKNOPOINT) case TCL112AC: + case TEKNOPOINT: { IRTcl112Ac ac(_pin, _inverted, _modulation); - tcl112(&ac, send.power, send.mode, degC, send.fanspeed, send.swingv, - send.swingh, send.quiet, send.turbo, send.light, send.econo, - send.filter); + tcl_ac_remote_model_t model = (tcl_ac_remote_model_t)send.model; + if (send.protocol == decode_type_t::TEKNOPOINT) + model = tcl_ac_remote_model_t::GZ055BE1; + tcl112(&ac, model, send.power, send.mode, + degC, send.fanspeed, send.swingv, send.swingh, send.quiet, + send.turbo, send.light, send.econo, send.filter); break; } -#endif // SEND_TCL112AC +#endif // (SEND_TCL112AC || SEND_TEKNOPOINT) #if SEND_TECHNIBEL_AC case TECHNIBEL_AC: { @@ -3048,25 +3173,31 @@ bool IRac::hasStateChanged(void) { return cmpStates(next, _prev); } /// @return The equivalent enum. stdAc::opmode_t IRac::strToOpmode(const char *str, const stdAc::opmode_t def) { - if (!strcasecmp(str, kAutoStr) || - !strcasecmp(str, kAutomaticStr)) + if (!STRCASECMP(str, kAutoStr) || + !STRCASECMP(str, kAutomaticStr)) return stdAc::opmode_t::kAuto; - else if (!strcasecmp(str, kOffStr) || - !strcasecmp(str, kStopStr)) + else if (!STRCASECMP(str, kOffStr) || + !STRCASECMP(str, kStopStr)) return stdAc::opmode_t::kOff; - else if (!strcasecmp(str, kCoolStr) || - !strcasecmp(str, "COOLING")) + else if (!STRCASECMP(str, kCoolStr) || + !STRCASECMP(str, kCoolingStr)) return stdAc::opmode_t::kCool; - else if (!strcasecmp(str, kHeatStr) || - !strcasecmp(str, "HEATING")) + else if (!STRCASECMP(str, kHeatStr) || + !STRCASECMP(str, kHeatingStr)) return stdAc::opmode_t::kHeat; - else if (!strcasecmp(str, kDryStr) || - !strcasecmp(str, "DRYING") || - !strcasecmp(str, "DEHUMIDIFY")) + else if (!STRCASECMP(str, kDryStr) || + !STRCASECMP(str, kDryingStr) || + !STRCASECMP(str, kDehumidifyStr)) return stdAc::opmode_t::kDry; - else if (!strcasecmp(str, kFanStr) || - !strcasecmp(str, "FANONLY") || - !strcasecmp(str, kFanOnlyStr)) + else if (!STRCASECMP(str, kFanStr) || + // The following Fans strings with "only" are required to help with + // HomeAssistant & Google Home Climate integration. + // For compatibility only. + // Ref: https://www.home-assistant.io/integrations/google_assistant/#climate-operation-modes + !STRCASECMP(str, kFanOnlyStr) || + !STRCASECMP(str, kFan_OnlyStr) || + !STRCASECMP(str, kFanOnlyWithSpaceStr) || + !STRCASECMP(str, kFanOnlyNoSpaceStr)) return stdAc::opmode_t::kFan; else return def; @@ -3078,26 +3209,26 @@ stdAc::opmode_t IRac::strToOpmode(const char *str, /// @return The equivalent enum. stdAc::fanspeed_t IRac::strToFanspeed(const char *str, const stdAc::fanspeed_t def) { - if (!strcasecmp(str, kAutoStr) || - !strcasecmp(str, kAutomaticStr)) + if (!STRCASECMP(str, kAutoStr) || + !STRCASECMP(str, kAutomaticStr)) return stdAc::fanspeed_t::kAuto; - else if (!strcasecmp(str, kMinStr) || - !strcasecmp(str, kMinimumStr) || - !strcasecmp(str, kLowestStr)) + else if (!STRCASECMP(str, kMinStr) || + !STRCASECMP(str, kMinimumStr) || + !STRCASECMP(str, kLowestStr)) return stdAc::fanspeed_t::kMin; - else if (!strcasecmp(str, kLowStr) || - !strcasecmp(str, kLoStr)) + else if (!STRCASECMP(str, kLowStr) || + !STRCASECMP(str, kLoStr)) return stdAc::fanspeed_t::kLow; - else if (!strcasecmp(str, kMedStr) || - !strcasecmp(str, kMediumStr) || - !strcasecmp(str, kMidStr)) + else if (!STRCASECMP(str, kMedStr) || + !STRCASECMP(str, kMediumStr) || + !STRCASECMP(str, kMidStr)) return stdAc::fanspeed_t::kMedium; - else if (!strcasecmp(str, kHighStr) || - !strcasecmp(str, kHiStr)) + else if (!STRCASECMP(str, kHighStr) || + !STRCASECMP(str, kHiStr)) return stdAc::fanspeed_t::kHigh; - else if (!strcasecmp(str, kMaxStr) || - !strcasecmp(str, kMaximumStr) || - !strcasecmp(str, kHighestStr)) + else if (!STRCASECMP(str, kMaxStr) || + !STRCASECMP(str, kMaximumStr) || + !STRCASECMP(str, kHighestStr)) return stdAc::fanspeed_t::kMax; else return def; @@ -3109,36 +3240,36 @@ stdAc::fanspeed_t IRac::strToFanspeed(const char *str, /// @return The equivalent enum. stdAc::swingv_t IRac::strToSwingV(const char *str, const stdAc::swingv_t def) { - if (!strcasecmp(str, kAutoStr) || - !strcasecmp(str, kAutomaticStr) || - !strcasecmp(str, kOnStr) || - !strcasecmp(str, kSwingStr)) + if (!STRCASECMP(str, kAutoStr) || + !STRCASECMP(str, kAutomaticStr) || + !STRCASECMP(str, kOnStr) || + !STRCASECMP(str, kSwingStr)) return stdAc::swingv_t::kAuto; - else if (!strcasecmp(str, kOffStr) || - !strcasecmp(str, kStopStr)) + else if (!STRCASECMP(str, kOffStr) || + !STRCASECMP(str, kStopStr)) return stdAc::swingv_t::kOff; - else if (!strcasecmp(str, kMinStr) || - !strcasecmp(str, kMinimumStr) || - !strcasecmp(str, kLowestStr) || - !strcasecmp(str, kBottomStr) || - !strcasecmp(str, kDownStr)) + else if (!STRCASECMP(str, kMinStr) || + !STRCASECMP(str, kMinimumStr) || + !STRCASECMP(str, kLowestStr) || + !STRCASECMP(str, kBottomStr) || + !STRCASECMP(str, kDownStr)) return stdAc::swingv_t::kLowest; - else if (!strcasecmp(str, kLowStr)) + else if (!STRCASECMP(str, kLowStr)) return stdAc::swingv_t::kLow; - else if (!strcasecmp(str, kMidStr) || - !strcasecmp(str, kMiddleStr) || - !strcasecmp(str, kMedStr) || - !strcasecmp(str, kMediumStr) || - !strcasecmp(str, kCentreStr)) + else if (!STRCASECMP(str, kMidStr) || + !STRCASECMP(str, kMiddleStr) || + !STRCASECMP(str, kMedStr) || + !STRCASECMP(str, kMediumStr) || + !STRCASECMP(str, kCentreStr)) return stdAc::swingv_t::kMiddle; - else if (!strcasecmp(str, kHighStr) || - !strcasecmp(str, kHiStr)) + else if (!STRCASECMP(str, kHighStr) || + !STRCASECMP(str, kHiStr)) return stdAc::swingv_t::kHigh; - else if (!strcasecmp(str, kHighestStr) || - !strcasecmp(str, kMaxStr) || - !strcasecmp(str, kMaximumStr) || - !strcasecmp(str, kTopStr) || - !strcasecmp(str, kUpStr)) + else if (!STRCASECMP(str, kHighestStr) || + !STRCASECMP(str, kMaxStr) || + !STRCASECMP(str, kMaximumStr) || + !STRCASECMP(str, kTopStr) || + !STRCASECMP(str, kUpStr)) return stdAc::swingv_t::kHighest; else return def; @@ -3150,34 +3281,34 @@ stdAc::swingv_t IRac::strToSwingV(const char *str, /// @return The equivalent enum. stdAc::swingh_t IRac::strToSwingH(const char *str, const stdAc::swingh_t def) { - if (!strcasecmp(str, kAutoStr) || - !strcasecmp(str, kAutomaticStr) || - !strcasecmp(str, kOnStr) || !strcasecmp(str, kSwingStr)) + if (!STRCASECMP(str, kAutoStr) || + !STRCASECMP(str, kAutomaticStr) || + !STRCASECMP(str, kOnStr) || !STRCASECMP(str, kSwingStr)) return stdAc::swingh_t::kAuto; - else if (!strcasecmp(str, kOffStr) || - !strcasecmp(str, kStopStr)) + else if (!STRCASECMP(str, kOffStr) || + !STRCASECMP(str, kStopStr)) return stdAc::swingh_t::kOff; - else if (!strcasecmp(str, kLeftMaxStr) || // "LeftMax" - !strcasecmp(str, D_STR_LEFT " " D_STR_MAX) || // "Left Max" - !strcasecmp(str, D_STR_MAX D_STR_LEFT) || // "MaxLeft" - !strcasecmp(str, kMaxLeftStr)) // "Max Left" + else if (!STRCASECMP(str, kLeftMaxNoSpaceStr) || // "LeftMax" + !STRCASECMP(str, kLeftMaxStr) || // "Left Max" + !STRCASECMP(str, kMaxLeftNoSpaceStr) || // "MaxLeft" + !STRCASECMP(str, kMaxLeftStr)) // "Max Left" return stdAc::swingh_t::kLeftMax; - else if (!strcasecmp(str, kLeftStr)) + else if (!STRCASECMP(str, kLeftStr)) return stdAc::swingh_t::kLeft; - else if (!strcasecmp(str, kMidStr) || - !strcasecmp(str, kMiddleStr) || - !strcasecmp(str, kMedStr) || - !strcasecmp(str, kMediumStr) || - !strcasecmp(str, kCentreStr)) + else if (!STRCASECMP(str, kMidStr) || + !STRCASECMP(str, kMiddleStr) || + !STRCASECMP(str, kMedStr) || + !STRCASECMP(str, kMediumStr) || + !STRCASECMP(str, kCentreStr)) return stdAc::swingh_t::kMiddle; - else if (!strcasecmp(str, kRightStr)) + else if (!STRCASECMP(str, kRightStr)) return stdAc::swingh_t::kRight; - else if (!strcasecmp(str, kRightMaxStr) || // "RightMax" - !strcasecmp(str, D_STR_RIGHT " " D_STR_MAX) || // "Right Max" - !strcasecmp(str, D_STR_MAX D_STR_RIGHT) || // "MaxRight" - !strcasecmp(str, kMaxRightStr)) // "Max Right" + else if (!STRCASECMP(str, kRightMaxNoSpaceStr) || // "RightMax" + !STRCASECMP(str, kRightMaxStr) || // "Right Max" + !STRCASECMP(str, kMaxRightNoSpaceStr) || // "MaxRight" + !STRCASECMP(str, kMaxRightStr)) // "Max Right" return stdAc::swingh_t::kRightMax; - else if (!strcasecmp(str, kWideStr)) + else if (!STRCASECMP(str, kWideStr)) return stdAc::swingh_t::kWide; else return def; @@ -3188,59 +3319,86 @@ stdAc::swingh_t IRac::strToSwingH(const char *str, /// @param[in] str A Ptr to a C-style string to be converted. /// @param[in] def The enum to return if no conversion was possible. /// @return The equivalent enum. +/// @note After adding a new model you should update modelToStr() too. int16_t IRac::strToModel(const char *str, const int16_t def) { // Gree - if (!strcasecmp(str, "YAW1F")) { + if (!STRCASECMP(str, kYaw1fStr)) { return gree_ac_remote_model_t::YAW1F; - } else if (!strcasecmp(str, "YBOFB")) { + } else if (!STRCASECMP(str, kYbofbStr)) { return gree_ac_remote_model_t::YBOFB; + // Haier models + } else if (!STRCASECMP(str, kV9014557AStr)) { + return haier_ac176_remote_model_t::V9014557_A; + } else if (!STRCASECMP(str, kV9014557BStr)) { + return haier_ac176_remote_model_t::V9014557_B; // HitachiAc1 models - } else if (!strcasecmp(str, "R-LT0541-HTA-A")) { + } else if (!STRCASECMP(str, kRlt0541htaaStr)) { return hitachi_ac1_remote_model_t::R_LT0541_HTA_A; - } else if (!strcasecmp(str, "R-LT0541-HTA-B")) { + } else if (!STRCASECMP(str, kRlt0541htabStr)) { return hitachi_ac1_remote_model_t::R_LT0541_HTA_B; // Fujitsu A/C models - } else if (!strcasecmp(str, "ARRAH2E")) { + } else if (!STRCASECMP(str, kArrah2eStr)) { return fujitsu_ac_remote_model_t::ARRAH2E; - } else if (!strcasecmp(str, "ARDB1")) { + } else if (!STRCASECMP(str, kArdb1Str)) { return fujitsu_ac_remote_model_t::ARDB1; - } else if (!strcasecmp(str, "ARREB1E")) { + } else if (!STRCASECMP(str, kArreb1eStr)) { return fujitsu_ac_remote_model_t::ARREB1E; - } else if (!strcasecmp(str, "ARJW2")) { + } else if (!STRCASECMP(str, kArjw2Str)) { return fujitsu_ac_remote_model_t::ARJW2; - } else if (!strcasecmp(str, "ARRY4")) { + } else if (!STRCASECMP(str, kArry4Str)) { return fujitsu_ac_remote_model_t::ARRY4; + } else if (!STRCASECMP(str, kArrew4eStr)) { + return fujitsu_ac_remote_model_t::ARREW4E; // LG A/C models - } else if (!strcasecmp(str, "GE6711AR2853M")) { + } else if (!STRCASECMP(str, kGe6711ar2853mStr)) { return lg_ac_remote_model_t::GE6711AR2853M; - } else if (!strcasecmp(str, "AKB75215403")) { + } else if (!STRCASECMP(str, kAkb75215403Str)) { return lg_ac_remote_model_t::AKB75215403; - } else if (!strcasecmp(str, "AKB74955603")) { + } else if (!STRCASECMP(str, kAkb74955603Str)) { return lg_ac_remote_model_t::AKB74955603; - } else if (!strcasecmp(str, "AKB73757604")) { + } else if (!STRCASECMP(str, kAkb73757604Str)) { return lg_ac_remote_model_t::AKB73757604; // Panasonic A/C families - } else if (!strcasecmp(str, "LKE") || !strcasecmp(str, "PANASONICLKE")) { + } else if (!STRCASECMP(str, kLkeStr) || + !STRCASECMP(str, kPanasonicLkeStr)) { return panasonic_ac_remote_model_t::kPanasonicLke; - } else if (!strcasecmp(str, "NKE") || !strcasecmp(str, "PANASONICNKE")) { + } else if (!STRCASECMP(str, kNkeStr) || + !STRCASECMP(str, kPanasonicNkeStr)) { return panasonic_ac_remote_model_t::kPanasonicNke; - } else if (!strcasecmp(str, "DKE") || !strcasecmp(str, "PANASONICDKE") || - !strcasecmp(str, "PKR") || !strcasecmp(str, "PANASONICPKR")) { + } else if (!STRCASECMP(str, kDkeStr) || + !STRCASECMP(str, kPanasonicDkeStr) || + !STRCASECMP(str, kPkrStr) || + !STRCASECMP(str, kPanasonicPkrStr)) { return panasonic_ac_remote_model_t::kPanasonicDke; - } else if (!strcasecmp(str, "JKE") || !strcasecmp(str, "PANASONICJKE")) { + } else if (!STRCASECMP(str, kJkeStr) || + !STRCASECMP(str, kPanasonicJkeStr)) { return panasonic_ac_remote_model_t::kPanasonicJke; - } else if (!strcasecmp(str, "CKP") || !strcasecmp(str, "PANASONICCKP")) { + } else if (!STRCASECMP(str, kCkpStr) || + !STRCASECMP(str, kPanasonicCkpStr)) { return panasonic_ac_remote_model_t::kPanasonicCkp; - } else if (!strcasecmp(str, "RKR") || !strcasecmp(str, "PANASONICRKR")) { + } else if (!STRCASECMP(str, kRkrStr) || + !STRCASECMP(str, kPanasonicRkrStr)) { return panasonic_ac_remote_model_t::kPanasonicRkr; + // Sharp A/C Models + } else if (!STRCASECMP(str, kA907Str)) { + return sharp_ac_remote_model_t::A907; + } else if (!STRCASECMP(str, kA705Str)) { + return sharp_ac_remote_model_t::A705; + } else if (!STRCASECMP(str, kA903Str)) { + return sharp_ac_remote_model_t::A903; + // TCL A/C Models + } else if (!STRCASECMP(str, kTac09chsdStr)) { + return tcl_ac_remote_model_t::TAC09CHSD; + } else if (!STRCASECMP(str, kGz055be1Str)) { + return tcl_ac_remote_model_t::GZ055BE1; // Voltas A/C models - } else if (!strcasecmp(str, "122LZF")) { + } else if (!STRCASECMP(str, k122lzfStr)) { return voltas_ac_remote_model_t::kVoltas122LZF; // Whirlpool A/C models - } else if (!strcasecmp(str, "DG11J13A") || !strcasecmp(str, "DG11J104") || - !strcasecmp(str, "DG11J1-04")) { + } else if (!STRCASECMP(str, kDg11j13aStr) || + !STRCASECMP(str, kDg11j104Str)) { return whirlpool_ac_remote_model_t::DG11J13A; - } else if (!strcasecmp(str, "DG11J191")) { + } else if (!STRCASECMP(str, kDg11j191Str)) { return whirlpool_ac_remote_model_t::DG11J191; } else { int16_t number = atoi(str); @@ -3256,15 +3414,15 @@ int16_t IRac::strToModel(const char *str, const int16_t def) { /// @param[in] def The boolean value to return if no conversion was possible. /// @return The equivalent boolean value. bool IRac::strToBool(const char *str, const bool def) { - if (!strcasecmp(str, kOnStr) || - !strcasecmp(str, "1") || - !strcasecmp(str, kYesStr) || - !strcasecmp(str, kTrueStr)) + if (!STRCASECMP(str, kOnStr) || + !STRCASECMP(str, k1Str) || + !STRCASECMP(str, kYesStr) || + !STRCASECMP(str, kTrueStr)) return true; - else if (!strcasecmp(str, kOffStr) || - !strcasecmp(str, "0") || - !strcasecmp(str, kNoStr) || - !strcasecmp(str, kFalseStr)) + else if (!STRCASECMP(str, kOffStr) || + !STRCASECMP(str, k0Str) || + !STRCASECMP(str, kNoStr) || + !STRCASECMP(str, kFalseStr)) return false; else return def; @@ -3279,23 +3437,17 @@ String IRac::boolToString(const bool value) { /// Convert the supplied operation mode into the appropriate String. /// @param[in] mode The enum to be converted. +/// @param[in] ha A flag to indicate we want GoogleHome/HomeAssistant output. /// @return The equivalent String for the locale. -String IRac::opmodeToString(const stdAc::opmode_t mode) { +String IRac::opmodeToString(const stdAc::opmode_t mode, const bool ha) { switch (mode) { - case stdAc::opmode_t::kOff: - return kOffStr; - case stdAc::opmode_t::kAuto: - return kAutoStr; - case stdAc::opmode_t::kCool: - return kCoolStr; - case stdAc::opmode_t::kHeat: - return kHeatStr; - case stdAc::opmode_t::kDry: - return kDryStr; - case stdAc::opmode_t::kFan: - return kFanOnlyStr; - default: - return kUnknownStr; + case stdAc::opmode_t::kOff: return kOffStr; + case stdAc::opmode_t::kAuto: return kAutoStr; + case stdAc::opmode_t::kCool: return kCoolStr; + case stdAc::opmode_t::kHeat: return kHeatStr; + case stdAc::opmode_t::kDry: return kDryStr; + case stdAc::opmode_t::kFan: return ha ? kFan_OnlyStr : kFanStr; + default: return kUnknownStr; } } @@ -3304,20 +3456,13 @@ String IRac::opmodeToString(const stdAc::opmode_t mode) { /// @return The equivalent String for the locale. String IRac::fanspeedToString(const stdAc::fanspeed_t speed) { switch (speed) { - case stdAc::fanspeed_t::kAuto: - return kAutoStr; - case stdAc::fanspeed_t::kMax: - return kMaxStr; - case stdAc::fanspeed_t::kHigh: - return kHighStr; - case stdAc::fanspeed_t::kMedium: - return kMediumStr; - case stdAc::fanspeed_t::kLow: - return kLowStr; - case stdAc::fanspeed_t::kMin: - return kMinStr; - default: - return kUnknownStr; + case stdAc::fanspeed_t::kAuto: return kAutoStr; + case stdAc::fanspeed_t::kMax: return kMaxStr; + case stdAc::fanspeed_t::kHigh: return kHighStr; + case stdAc::fanspeed_t::kMedium: return kMediumStr; + case stdAc::fanspeed_t::kLow: return kLowStr; + case stdAc::fanspeed_t::kMin: return kMinStr; + default: return kUnknownStr; } } @@ -3326,22 +3471,14 @@ String IRac::fanspeedToString(const stdAc::fanspeed_t speed) { /// @return The equivalent String for the locale. String IRac::swingvToString(const stdAc::swingv_t swingv) { switch (swingv) { - case stdAc::swingv_t::kOff: - return kOffStr; - case stdAc::swingv_t::kAuto: - return kAutoStr; - case stdAc::swingv_t::kHighest: - return kHighestStr; - case stdAc::swingv_t::kHigh: - return kHighStr; - case stdAc::swingv_t::kMiddle: - return kMiddleStr; - case stdAc::swingv_t::kLow: - return kLowStr; - case stdAc::swingv_t::kLowest: - return kLowestStr; - default: - return kUnknownStr; + case stdAc::swingv_t::kOff: return kOffStr; + case stdAc::swingv_t::kAuto: return kAutoStr; + case stdAc::swingv_t::kHighest: return kHighestStr; + case stdAc::swingv_t::kHigh: return kHighStr; + case stdAc::swingv_t::kMiddle: return kMiddleStr; + case stdAc::swingv_t::kLow: return kLowStr; + case stdAc::swingv_t::kLowest: return kLowestStr; + default: return kUnknownStr; } } @@ -3350,24 +3487,15 @@ String IRac::swingvToString(const stdAc::swingv_t swingv) { /// @return The equivalent String for the locale. String IRac::swinghToString(const stdAc::swingh_t swingh) { switch (swingh) { - case stdAc::swingh_t::kOff: - return kOffStr; - case stdAc::swingh_t::kAuto: - return kAutoStr; - case stdAc::swingh_t::kLeftMax: - return kLeftMaxStr; - case stdAc::swingh_t::kLeft: - return kLeftStr; - case stdAc::swingh_t::kMiddle: - return kMiddleStr; - case stdAc::swingh_t::kRight: - return kRightStr; - case stdAc::swingh_t::kRightMax: - return kRightMaxStr; - case stdAc::swingh_t::kWide: - return kWideStr; - default: - return kUnknownStr; + case stdAc::swingh_t::kOff: return kOffStr; + case stdAc::swingh_t::kAuto: return kAutoStr; + case stdAc::swingh_t::kLeftMax: return kLeftMaxStr; + case stdAc::swingh_t::kLeft: return kLeftStr; + case stdAc::swingh_t::kMiddle: return kMiddleStr; + case stdAc::swingh_t::kRight: return kRightStr; + case stdAc::swingh_t::kRightMax: return kRightMaxStr; + case stdAc::swingh_t::kWide: return kWideStr; + default: return kUnknownStr; } } @@ -3407,6 +3535,21 @@ namespace IRAcUtils { return ac.toString(); } #endif // DECODE_CARRIER_AC64 +#if DECODE_COOLIX + case decode_type_t::COOLIX: { + IRCoolixAC ac(kGpioUnused); + ac.on(); + ac.setRaw(result->value); // Coolix uses value instead of state. + return ac.toString(); + } +#endif // DECODE_COOLIX +#if DECODE_CORONA_AC + case decode_type_t::CORONA_AC: { + IRCoronaAc ac(kGpioUnused); + ac.setRaw(result->state, result->bits / 8); + return ac.toString(); + } +#endif // DECODE_CORONA_AC #if DECODE_DAIKIN case decode_type_t::DAIKIN: { IRDaikinESP ac(kGpioUnused); @@ -3494,6 +3637,69 @@ namespace IRAcUtils { return ac.toString(); } #endif // DECODE_FUJITSU_AC +#if DECODE_GOODWEATHER + case decode_type_t::GOODWEATHER: { + IRGoodweatherAc ac(kGpioUnused); + ac.setRaw(result->value); // Goodweather uses value instead of state. + return ac.toString(); + } +#endif // DECODE_GOODWEATHER +#if DECODE_GREE + case decode_type_t::GREE: { + IRGreeAC ac(kGpioUnused); + ac.setRaw(result->state); + return ac.toString(); + } +#endif // DECODE_GREE +#if DECODE_HAIER_AC + case decode_type_t::HAIER_AC: { + IRHaierAC ac(kGpioUnused); + ac.setRaw(result->state); + return ac.toString(); + } +#endif // DECODE_HAIER_AC +#if DECODE_HAIER_AC176 + case decode_type_t::HAIER_AC176: { + IRHaierAC176 ac(kGpioUnused); + ac.setRaw(result->state); + return ac.toString(); + } +#endif // DECODE_HAIER_AC176 +#if DECODE_HAIER_AC_YRW02 + case decode_type_t::HAIER_AC_YRW02: { + IRHaierACYRW02 ac(kGpioUnused); + ac.setRaw(result->state); + return ac.toString(); + } +#endif // DECODE_HAIER_AC_YRW02 +#if DECODE_HITACHI_AC + case decode_type_t::HITACHI_AC: { + IRHitachiAc ac(kGpioUnused); + ac.setRaw(result->state); + return ac.toString(); + } +#endif // DECODE_HITACHI_AC +#if DECODE_HITACHI_AC1 + case decode_type_t::HITACHI_AC1: { + IRHitachiAc1 ac(kGpioUnused); + ac.setRaw(result->state); + return ac.toString(); + } +#endif // DECODE_HITACHI_AC1 +#if DECODE_HITACHI_AC344 + case decode_type_t::HITACHI_AC344: { + IRHitachiAc344 ac(kGpioUnused); + ac.setRaw(result->state); + return ac.toString(); + } +#endif // DECODE_HITACHI_AC344 +#if DECODE_HITACHI_AC424 + case decode_type_t::HITACHI_AC424: { + IRHitachiAc424 ac(kGpioUnused); + ac.setRaw(result->state); + return ac.toString(); + } +#endif // DECODE_HITACHI_AC424 #if DECODE_KELON case decode_type_t::KELON: { IRKelonAc ac(kGpioUnused); @@ -3508,6 +3714,28 @@ namespace IRAcUtils { return ac.toString(); } #endif // DECODE_KELVINATOR +#if DECODE_LG + case decode_type_t::LG: + case decode_type_t::LG2: { + IRLgAc ac(kGpioUnused); + ac.setRaw(result->value, result->decode_type); // Use value, not state. + return ac.isValidLgAc() ? ac.toString() : ""; + } +#endif // DECODE_LG +#if DECODE_MIDEA + case decode_type_t::MIDEA: { + IRMideaAC ac(kGpioUnused); + ac.setRaw(result->value); // Midea uses value instead of state. + return ac.toString(); + } +#endif // DECODE_MIDEA +#if DECODE_MIRAGE + case decode_type_t::MIRAGE: { + IRMirageAc ac(kGpioUnused); + ac.setRaw(result->state); + return ac.toString(); + } +#endif // DECODE_MIRAGE #if DECODE_MITSUBISHI_AC case decode_type_t::MITSUBISHI_AC: { IRMitsubishiAC ac(kGpioUnused); @@ -3548,76 +3776,33 @@ namespace IRAcUtils { return ac.toString(); } #endif // DECODE_NEOCLIMA -#if DECODE_TOSHIBA_AC - case decode_type_t::TOSHIBA_AC: { - IRToshibaAC ac(kGpioUnused); - ac.setRaw(result->state, result->bits / 8); - return ac.toString(); +#if DECODE_PANASONIC_AC + case decode_type_t::PANASONIC_AC: { + if (result->bits > kPanasonicAcShortBits) { + IRPanasonicAc ac(kGpioUnused); + ac.setRaw(result->state); + return ac.toString(); + } + return ""; } -#endif // DECODE_TOSHIBA_AC -#if DECODE_TROTEC - case decode_type_t::TROTEC: { - IRTrotecESP ac(kGpioUnused); - ac.setRaw(result->state); - return ac.toString(); +#endif // DECODE_PANASONIC_AC +#if DECODE_PANASONIC_AC32 + case decode_type_t::PANASONIC_AC32: { + if (result->bits >= kPanasonicAc32Bits) { + IRPanasonicAc32 ac(kGpioUnused); + ac.setRaw(result->value); // Uses value instead of state. + return ac.toString(); + } + return ""; } -#endif // DECODE_TROTEC -#if DECODE_TROTEC_3550 - case decode_type_t::TROTEC_3550: { - IRTrotec3550 ac(kGpioUnused); - ac.setRaw(result->state); - return ac.toString(); - } -#endif // DECODE_TROTEC_3550 -#if DECODE_TRUMA - case decode_type_t::TRUMA: { - IRTrumaAc ac(kGpioUnused); - ac.setRaw(result->value); // Truma uses value instead of state. - return ac.toString(); - } -#endif // DECODE_TRUMA -#if DECODE_GOODWEATHER - case decode_type_t::GOODWEATHER: { - IRGoodweatherAc ac(kGpioUnused); - ac.setRaw(result->value); // Goodweather uses value instead of state. - return ac.toString(); - } -#endif // DECODE_GOODWEATHER -#if DECODE_GREE - case decode_type_t::GREE: { - IRGreeAC ac(kGpioUnused); - ac.setRaw(result->state); - return ac.toString(); - } -#endif // DECODE_GREE -#if DECODE_MIDEA - case decode_type_t::MIDEA: { - IRMideaAC ac(kGpioUnused); - ac.setRaw(result->value); // Midea uses value instead of state. - return ac.toString(); - } -#endif // DECODE_MIDEA -#if DECODE_HAIER_AC - case decode_type_t::HAIER_AC: { - IRHaierAC ac(kGpioUnused); - ac.setRaw(result->state); - return ac.toString(); - } -#endif // DECODE_HAIER_AC -#if DECODE_HAIER_AC176 - case decode_type_t::HAIER_AC176: { - IRHaierAC176 ac(kGpioUnused); - ac.setRaw(result->state); - return ac.toString(); - } -#endif // DECODE_HAIER_AC176 -#if DECODE_HAIER_AC_YRW02 - case decode_type_t::HAIER_AC_YRW02: { - IRHaierACYRW02 ac(kGpioUnused); - ac.setRaw(result->state); - return ac.toString(); - } -#endif // DECODE_HAIER_AC_YRW02 +#endif // DECODE_PANASONIC_AC +#if DECODE_RHOSS + case decode_type_t::RHOSS: { + IRRhossAc ac(kGpioUnused); + ac.setRaw(result->state); + return ac.toString(); + } +#endif // DECODE_RHOSS #if DECODE_SAMSUNG_AC case decode_type_t::SAMSUNG_AC: { IRSamsungAc ac(kGpioUnused); @@ -3646,83 +3831,14 @@ namespace IRAcUtils { return ac.toString(); } #endif // DECODE_SHARP_AC -#if DECODE_COOLIX - case decode_type_t::COOLIX: { - IRCoolixAC ac(kGpioUnused); - ac.on(); - ac.setRaw(result->value); // Coolix uses value instead of state. - return ac.toString(); - } -#endif // DECODE_COOLIX -#if DECODE_CORONA_AC - case decode_type_t::CORONA_AC: { - IRCoronaAc ac(kGpioUnused); - ac.setRaw(result->state, result->bits / 8); - return ac.toString(); - } -#endif // DECODE_CORONA_AC -#if DECODE_PANASONIC_AC - case decode_type_t::PANASONIC_AC: { - if (result->bits > kPanasonicAcShortBits) { - IRPanasonicAc ac(kGpioUnused); - ac.setRaw(result->state); - return ac.toString(); - } - return ""; - } -#endif // DECODE_PANASONIC_AC -#if DECODE_PANASONIC_AC32 - case decode_type_t::PANASONIC_AC32: { - if (result->bits >= kPanasonicAc32Bits) { - IRPanasonicAc32 ac(kGpioUnused); - ac.setRaw(result->value); // Uses value instead of state. - return ac.toString(); - } - return ""; - } -#endif // DECODE_PANASONIC_AC -#if DECODE_HITACHI_AC - case decode_type_t::HITACHI_AC: { - IRHitachiAc ac(kGpioUnused); +#if (DECODE_TCL112AC || DECODE_TEKNOPOINT) + case decode_type_t::TCL112AC: + case decode_type_t::TEKNOPOINT: { + IRTcl112Ac ac(kGpioUnused); ac.setRaw(result->state); return ac.toString(); } -#endif // DECODE_HITACHI_AC -#if DECODE_HITACHI_AC1 - case decode_type_t::HITACHI_AC1: { - IRHitachiAc1 ac(kGpioUnused); - ac.setRaw(result->state); - return ac.toString(); - } -#endif // DECODE_HITACHI_AC1 -#if DECODE_HITACHI_AC344 - case decode_type_t::HITACHI_AC344: { - IRHitachiAc344 ac(kGpioUnused); - ac.setRaw(result->state); - return ac.toString(); - } -#endif // DECODE_HITACHI_AC344 -#if DECODE_HITACHI_AC424 - case decode_type_t::HITACHI_AC424: { - IRHitachiAc424 ac(kGpioUnused); - ac.setRaw(result->state); - return ac.toString(); - } -#endif // DECODE_HITACHI_AC424 -#if DECODE_WHIRLPOOL_AC - case decode_type_t::WHIRLPOOL_AC: { - IRWhirlpoolAc ac(kGpioUnused); - ac.setRaw(result->state); - return ac.toString(); - } -#endif // DECODE_WHIRLPOOL_AC -#if DECODE_VESTEL_AC - case decode_type_t::VESTEL_AC: { - IRVestelAc ac(kGpioUnused); - ac.setRaw(result->value); // Like Coolix, use value instead of state. - return ac.toString(); - } -#endif // DECODE_VESTEL_AC +#endif // (DECODE_TCL112AC || DECODE_TEKNOPOINT) #if DECODE_TECHNIBEL_AC case decode_type_t::TECHNIBEL_AC: { IRTechnibelAc ac(kGpioUnused); @@ -3730,13 +3846,6 @@ namespace IRAcUtils { return ac.toString(); } #endif // DECODE_TECHNIBEL_AC -#if DECODE_VOLTAS - case decode_type_t::VOLTAS: { - IRVoltas ac(kGpioUnused); - ac.setRaw(result->state); - return ac.toString(); - } -#endif // DECODE_VOLTAS #if DECODE_TECO case decode_type_t::TECO: { IRTecoAc ac(kGpioUnused); @@ -3744,21 +3853,13 @@ namespace IRAcUtils { return ac.toString(); } #endif // DECODE_TECO -#if DECODE_TCL112AC - case decode_type_t::TCL112AC: { - IRTcl112Ac ac(kGpioUnused); - ac.setRaw(result->state); +#if DECODE_TOSHIBA_AC + case decode_type_t::TOSHIBA_AC: { + IRToshibaAC ac(kGpioUnused); + ac.setRaw(result->state, result->bits / 8); return ac.toString(); } -#endif // DECODE_TCL112AC -#if DECODE_LG - case decode_type_t::LG: - case decode_type_t::LG2: { - IRLgAc ac(kGpioUnused); - ac.setRaw(result->value, result->decode_type); // Use value, not state. - return ac.isValidLgAc() ? ac.toString() : ""; - } -#endif // DECODE_LG +#endif // DECODE_TOSHIBA_AC #if DECODE_TRANSCOLD case decode_type_t::TRANSCOLD: { IRTranscoldAc ac(kGpioUnused); @@ -3767,6 +3868,48 @@ namespace IRAcUtils { return ac.toString(); } #endif // DECODE_TRANSCOLD +#if DECODE_TROTEC + case decode_type_t::TROTEC: { + IRTrotecESP ac(kGpioUnused); + ac.setRaw(result->state); + return ac.toString(); + } +#endif // DECODE_TROTEC +#if DECODE_TROTEC_3550 + case decode_type_t::TROTEC_3550: { + IRTrotec3550 ac(kGpioUnused); + ac.setRaw(result->state); + return ac.toString(); + } +#endif // DECODE_TROTEC_3550 +#if DECODE_TRUMA + case decode_type_t::TRUMA: { + IRTrumaAc ac(kGpioUnused); + ac.setRaw(result->value); // Truma uses value instead of state. + return ac.toString(); + } +#endif // DECODE_TRUMA +#if DECODE_VESTEL_AC + case decode_type_t::VESTEL_AC: { + IRVestelAc ac(kGpioUnused); + ac.setRaw(result->value); // Like Coolix, use value instead of state. + return ac.toString(); + } +#endif // DECODE_VESTEL_AC +#if DECODE_VOLTAS + case decode_type_t::VOLTAS: { + IRVoltas ac(kGpioUnused); + ac.setRaw(result->state); + return ac.toString(); + } +#endif // DECODE_VOLTAS +#if DECODE_WHIRLPOOL_AC + case decode_type_t::WHIRLPOOL_AC: { + IRWhirlpoolAc ac(kGpioUnused); + ac.setRaw(result->state); + return ac.toString(); + } +#endif // DECODE_WHIRLPOOL_AC default: return ""; } @@ -3812,6 +3955,14 @@ namespace IRAcUtils { break; } #endif // DECODE_ARGO +#if DECODE_CARRIER_AC64 + case decode_type_t::CARRIER_AC64: { + IRCarrierAc64 ac(kGpioUnused); + ac.setRaw(decode->value); // Uses value instead of state. + *result = ac.toCommon(); + break; + } +#endif // DECODE_CARRIER_AC64 #if DECODE_COOLIX case decode_type_t::COOLIX: { IRCoolixAC ac(kGpioUnused); @@ -3828,14 +3979,6 @@ namespace IRAcUtils { break; } #endif // DECODE_CARRIER_AC64 -#if DECODE_CARRIER_AC64 - case decode_type_t::CARRIER_AC64: { - IRCarrierAc64 ac(kGpioUnused); - ac.setRaw(decode->value); // Uses value instead of state. - *result = ac.toCommon(); - break; - } -#endif // DECODE_CARRIER_AC64 #if DECODE_DAIKIN case decode_type_t::DAIKIN: { IRDaikinESP ac(kGpioUnused); @@ -4042,6 +4185,14 @@ namespace IRAcUtils { break; } #endif // DECODE_MIDEA +#if DECODE_MIRAGE + case decode_type_t::MIRAGE: { + IRMirageAc ac(kGpioUnused); + ac.setRaw(decode->state); + *result = ac.toCommon(); + break; + } +#endif // DECODE_MIRAGE #if DECODE_MITSUBISHI_AC case decode_type_t::MITSUBISHI_AC: { IRMitsubishiAC ac(kGpioUnused); @@ -4108,6 +4259,14 @@ namespace IRAcUtils { break; } #endif // DECODE_PANASONIC_AC32 +#if DECODE_RHOSS + case decode_type_t::RHOSS: { + IRRhossAc ac(kGpioUnused); + ac.setRaw(decode->state); + *result = ac.toCommon(); + break; + } +#endif // DECODE_RHOSS #if DECODE_SAMSUNG_AC case decode_type_t::SAMSUNG_AC: { IRSamsungAc ac(kGpioUnused); @@ -4136,18 +4295,22 @@ namespace IRAcUtils { case decode_type_t::SHARP_AC: { IRSharpAc ac(kGpioUnused); ac.setRaw(decode->state); - *result = ac.toCommon(); - break; - } -#endif // DECODE_SHARP_AC -#if DECODE_TCL112AC - case decode_type_t::TCL112AC: { - IRTcl112Ac ac(kGpioUnused); - ac.setRaw(decode->state); *result = ac.toCommon(prev); break; } -#endif // DECODE_TCL112AC +#endif // DECODE_SHARP_AC +#if (DECODE_TCL112AC || DECODE_TEKNOPOINT) + case decode_type_t::TCL112AC: + case decode_type_t::TEKNOPOINT: { + IRTcl112Ac ac(kGpioUnused); + ac.setRaw(decode->state); + *result = ac.toCommon(prev); + // Teknopoint uses the TCL protocol, but with a different model number. + // Just keep the original protocol type ... for now. + result->protocol = decode->decode_type; + break; + } +#endif // (DECODE_TCL112AC || DECODE_TEKNOPOINT) #if DECODE_TECHNIBEL_AC case decode_type_t::TECHNIBEL_AC: { IRTechnibelAc ac(kGpioUnused); @@ -4172,6 +4335,14 @@ namespace IRAcUtils { break; } #endif // DECODE_TOSHIBA_AC +#if DECODE_TRANSCOLD + case decode_type_t::TRANSCOLD: { + IRTranscoldAc ac(kGpioUnused); + ac.setRaw(decode->value); // TRANSCOLD Uses value instead of state. + *result = ac.toCommon(prev); + break; + } +#endif // DECODE_TRANSCOLD #if DECODE_TROTEC case decode_type_t::TROTEC: { IRTrotecESP ac(kGpioUnused); @@ -4220,14 +4391,6 @@ namespace IRAcUtils { break; } #endif // DECODE_WHIRLPOOL_AC -#if DECODE_TRANSCOLD - case decode_type_t::TRANSCOLD: { - IRTranscoldAc ac(kGpioUnused); - ac.setRaw(decode->value); // TRANSCOLD Uses value instead of state. - *result = ac.toCommon(prev); - break; - } -#endif // DECODE_TRANSCOLD default: return false; } diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRac.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRac.h index 573e7ae7e..afa4bcee0 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRac.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRac.h @@ -26,10 +26,12 @@ #include "ir_Kelvinator.h" #include "ir_LG.h" #include "ir_Midea.h" +#include "ir_Mirage.h" #include "ir_Mitsubishi.h" #include "ir_MitsubishiHeavy.h" #include "ir_Neoclima.h" #include "ir_Panasonic.h" +#include "ir_Rhoss.h" #include "ir_Samsung.h" #include "ir_Sanyo.h" #include "ir_Sharp.h" @@ -90,7 +92,8 @@ class IRac { static stdAc::swingh_t strToSwingH( const char *str, const stdAc::swingh_t def = stdAc::swingh_t::kOff); static String boolToString(const bool value); - static String opmodeToString(const stdAc::opmode_t mode); + static String opmodeToString(const stdAc::opmode_t mode, + const bool ha = false); static String fanspeedToString(const stdAc::fanspeed_t speed); static String swingvToString(const stdAc::swingv_t swingv); static String swinghToString(const stdAc::swingh_t swingh); @@ -245,7 +248,8 @@ void electra(IRElectraAc *ac, void gree(IRGreeAC *ac, const gree_ac_remote_model_t model, const bool on, const stdAc::opmode_t mode, const bool celsius, const float degrees, const stdAc::fanspeed_t fan, - const stdAc::swingv_t swingv, const bool turbo, const bool light, + const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, + const bool turbo, const bool econo, const bool light, const bool clean, const int16_t sleep = -1); #endif // SEND_GREE #if SEND_HAIER_AC @@ -257,18 +261,20 @@ void electra(IRElectraAc *ac, #endif // SEND_HAIER_AC #if SEND_HAIER_AC176 void haier176(IRHaierAC176 *ac, - const bool on, const stdAc::opmode_t mode, + const haier_ac176_remote_model_t model, const bool on, + const stdAc::opmode_t mode, const bool celsius, const float degrees, const stdAc::fanspeed_t fan, - const stdAc::swingv_t swingv, - const bool turbo, const bool filter, + const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, + const bool turbo, const bool quiet, const bool filter, const int16_t sleep = -1); #endif // SEND_HAIER_AC176 #if SEND_HAIER_AC_YRW02 void haierYrwo2(IRHaierACYRW02 *ac, const bool on, const stdAc::opmode_t mode, - const float degrees, const stdAc::fanspeed_t fan, - const stdAc::swingv_t swingv, - const bool turbo, const bool filter, + const bool celsius, const float degrees, + const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, + const stdAc::swingh_t swingh, const bool turbo, + const bool quiet, const bool filter, const int16_t sleep = -1); #endif // SEND_HAIER_AC_YRW02 #if SEND_HITACHI_AC @@ -326,6 +332,9 @@ void electra(IRElectraAc *ac, const stdAc::swingv_t swingv, const bool turbo, const bool econo, const bool light, const int16_t sleep = -1); #endif // SEND_MIDEA +#if SEND_MIRAGE + void mirage(IRMirageAc *ac, const stdAc::state_t state); +#endif // SEND_MIRAGE #if SEND_MITSUBISHI_AC void mitsubishi(IRMitsubishiAC *ac, const bool on, const stdAc::opmode_t mode, @@ -386,14 +395,21 @@ void electra(IRElectraAc *ac, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh); #endif // SEND_PANASONIC_AC32 +#if SEND_RHOSS + void rhoss(IRRhossAc *ac, + const bool on, const stdAc::opmode_t mode, const float degrees, + const stdAc::fanspeed_t fan, const stdAc::swingv_t swing); +#endif // SEND_RHOSS #if SEND_SAMSUNG_AC void samsung(IRSamsungAc *ac, const bool on, const stdAc::opmode_t mode, const float degrees, - const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, - const bool quiet, const bool turbo, const bool light, - const bool filter, const bool clean, - const bool beep, const bool prevpower = true, - const bool forcepower = true); + const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, + const bool quiet, const bool turbo, const bool econo, + const bool light, const bool filter, const bool clean, + const bool beep, const int16_t sleep = -1, + const bool prevpower = true, const int16_t prevsleep = -1, + const bool forceextended = true); #endif // SEND_SAMSUNG_AC #if SEND_SANYO_AC void sanyo(IRSanyoAc *ac, @@ -413,11 +429,12 @@ void electra(IRElectraAc *ac, void sharp(IRSharpAc *ac, const sharp_ac_remote_model_t model, const bool on, const bool prev_power, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, - const stdAc::swingv_t swingv, const bool turbo, const bool light, + const stdAc::swingv_t swingv, const stdAc::swingv_t swingv_prev, + const bool turbo, const bool light, const bool filter, const bool clean); #endif // SEND_SHARP_AC #if SEND_TCL112AC - void tcl112(IRTcl112Ac *ac, + void tcl112(IRTcl112Ac *ac, const tcl_ac_remote_model_t model, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRrecv.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRrecv.cpp index 9c7519cbd..4970dcf0b 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRrecv.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRrecv.cpp @@ -830,8 +830,7 @@ bool IRrecv::decode(decode_results *results, irparams_t *save, DPRINTLN("Attempting Samsung AC (extended) decode"); // Check the extended size first, as it should fail fast due to longer // length. - if (decodeSamsungAC(results, offset, kSamsungAcExtendedBits, false)) - return true; + if (decodeSamsungAC(results, offset, kSamsungAcExtendedBits)) return true; // Now check for the more common length. DPRINTLN("Attempting Samsung AC decode"); if (decodeSamsungAC(results, offset, kSamsungAcBits)) return true; @@ -1036,6 +1035,18 @@ bool IRrecv::decode(decode_results *results, irparams_t *save, DPRINTLN("Attempting Bose decode"); if (decodeBose(results, offset)) return true; #endif // DECODE_BOSE +#if DECODE_ARRIS + DPRINTLN("Attempting Arris decode"); + if (decodeArris(results, offset)) return true; +#endif // DECODE_ARRIS +#if DECODE_RHOSS + DPRINTLN("Attempting Rhoss decode"); + if (decodeRhoss(results, offset)) return true; +#endif // DECODE_RHOSS +#if DECODE_AIRTON + DPRINTLN("Attempting Airton decode"); + if (decodeAirton(results, offset)) return true; +#endif // DECODE_AIRTON // Typically new protocols are added above this line. } #if DECODE_HASH @@ -1811,6 +1822,7 @@ uint16_t IRrecv::matchManchesterData(volatile const uint16_t *data_ptr, const int16_t excess, const bool MSBfirst, const bool GEThomas) { + DPRINTLN("DEBUG: Entered matchManchesterData"); uint16_t offset = 0; uint64_t data = 0; uint16_t nr_half_periods = 0; @@ -1824,7 +1836,10 @@ uint16_t IRrecv::matchManchesterData(volatile const uint16_t *data_ptr, uint16_t min_remaining = nbits; // Check if there is enough capture buffer to possibly have the message. - if (remaining < min_remaining) return 0; // Nope, so abort. + if (remaining < min_remaining) { + DPRINTLN("DEBUG: Ran out of capture buffer!"); + return 0; // Nope, so abort. + } // Convert to ticks. Optimisation: Saves on math/extra instructions later. uint16_t bank = starting_balance / kRawTick; @@ -1847,22 +1862,39 @@ uint16_t IRrecv::matchManchesterData(volatile const uint16_t *data_ptr, while ((offset < remaining || bank) && nr_half_periods < expected_half_periods) { // Get the next entry if we haven't anything existing to process. + DPRINT("DEBUG: Offset = "); + DPRINTLN(offset); if (!bank) bank = *(data_ptr + offset++); + DPRINT("DEBUG: Bank = "); + DPRINTLN(bank * kRawTick); // Check if we don't have a short interval. - if (!match(bank, half_period, tolerance, excess)) return 0; // Not valid. + DPRINTLN("DEBUG: Checking for short interval"); + if (!match(bank, half_period, tolerance, excess)) { + DPRINTLN("DEBUG: It is. Exiting"); + return 0; // Not valid. + } // We've succeeded in matching half a period, so count it. nr_half_periods++; + DPRINT("DEBUG: Half Periods = "); + DPRINTLN(nr_half_periods); // We've now used up our bank, so refill it with the next item, unless we // are at the end of the capture buffer. // If we are assume a single half period of "space". - if (offset < remaining) + if (offset < remaining) { + DPRINT("DEBUG: Offset = "); + DPRINTLN(offset); bank = *(data_ptr + offset++); - else if (offset == remaining) + } else if (offset == remaining) { bank = raw_half_period; - else + } else { return 0; // We are out of buffer, so abort! + } + DPRINT("DEBUG: Bank = "); + DPRINTLN(bank * kRawTick); // Shift the data along and add our new bit. + DPRINT("DEBUG: Adding bit: "); + DPRINTLN((currentBit ? "1" : "0")); data <<= 1; data |= currentBit; @@ -1870,10 +1902,12 @@ uint16_t IRrecv::matchManchesterData(volatile const uint16_t *data_ptr, if (match(bank, half_period * 2, tolerance, excess)) { // It is, so flip the bit we need to append, and remove a half_period of // time from the bank. + DPRINTLN("DEBUG: long interval detected"); currentBit = !currentBit; bank -= raw_half_period; } else if (match(bank, half_period, tolerance, excess)) { // It is a short interval, so eat up all the time and move on. + DPRINTLN("DEBUG: short interval detected"); bank = 0; } else if (nr_half_periods == expected_half_periods - 1 && matchAtLeast(bank, half_period, tolerance, excess)) { diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRrecv.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRrecv.h index 1a883d509..f4932b5a6 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRrecv.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRrecv.h @@ -18,7 +18,7 @@ const uint16_t kHeader = 2; // Usual nr. of header entries. const uint16_t kFooter = 2; // Usual nr. of footer (stop bits) entries. const uint16_t kStartOffset = 1; // Usual rawbuf entry to start from. -#define MS_TO_USEC(x) (x * 1000U) // Convert milli-Seconds to micro-Seconds. +#define MS_TO_USEC(x) ((x) * 1000U) // Convert milli-Seconds to micro-Seconds. // Marks tend to be 100us too long, and spaces 100us too short // when received due to sensor lag. const uint16_t kMarkExcess = 50; @@ -287,6 +287,10 @@ class IRrecv { bool decodeArgo(decode_results *results, uint16_t offset = kStartOffset, const uint16_t nbits = kArgoBits, const bool strict = true); #endif // DECODE_ARGO +#if DECODE_ARRIS + bool decodeArris(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kArrisBits, const bool strict = true); +#endif // DECODE_ARRIS #if DECODE_SONY bool decodeSony(decode_results *results, uint16_t offset = kStartOffset, const uint16_t nbits = kSonyMinBits, @@ -766,6 +770,15 @@ class IRrecv { bool decodeBose(decode_results *results, uint16_t offset = kStartOffset, const uint16_t nbits = kBoseBits, const bool strict = true); #endif // DECODE_BOSE +#if DECODE_RHOSS + bool decodeRhoss(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kRhossBits, const bool strict = true); +#endif // DECODE_RHOSS +#if DECODE_AIRTON + bool decodeAirton(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kAirtonBits, + const bool strict = true); +#endif // DECODE_AIRTON }; #endif // IRRECV_H_ diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRremoteESP8266.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRremoteESP8266.h index 35b45d958..09a3011ce 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRremoteESP8266.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRremoteESP8266.h @@ -53,7 +53,7 @@ #endif // UNIT_TEST // Library Version -#define _IRREMOTEESP8266_VERSION_ "2.7.20" +#define _IRREMOTEESP8266_VERSION_ "2.8.0" // Set the language & locale for the library. See the `locale` dir for options. #ifndef _IR_LOCALE_ @@ -790,6 +790,27 @@ #define SEND_BOSE _IR_ENABLE_DEFAULT_ #endif // SEND_BOSE +#ifndef DECODE_ARRIS +#define DECODE_ARRIS _IR_ENABLE_DEFAULT_ +#endif // DECODE_ARRIS +#ifndef SEND_ARRIS +#define SEND_ARRIS _IR_ENABLE_DEFAULT_ +#endif // SEND_ARRIS + +#ifndef DECODE_RHOSS +#define DECODE_RHOSS _IR_ENABLE_DEFAULT_ +#endif // DECODE_RHOSS +#ifndef SEND_RHOSS +#define SEND_RHOSS _IR_ENABLE_DEFAULT_ +#endif // SEND_RHOSS + +#ifndef DECODE_AIRTON +#define DECODE_AIRTON _IR_ENABLE_DEFAULT_ +#endif // DECODE_AIRTON +#ifndef SEND_AIRTON +#define SEND_AIRTON _IR_ENABLE_DEFAULT_ +#endif // SEND_AIRTON + #if (DECODE_ARGO || DECODE_DAIKIN || DECODE_FUJITSU_AC || DECODE_GREE || \ DECODE_KELVINATOR || DECODE_MITSUBISHI_AC || DECODE_TOSHIBA_AC || \ DECODE_TROTEC || DECODE_HAIER_AC || DECODE_HITACHI_AC || \ @@ -804,7 +825,7 @@ DECODE_HITACHI_AC344 || DECODE_CORONA_AC || DECODE_SANYO_AC || \ DECODE_VOLTAS || DECODE_MIRAGE || DECODE_HAIER_AC176 || \ DECODE_TEKNOPOINT || DECODE_KELON || DECODE_TROTEC_3550 || \ - DECODE_SANYO_AC88 || \ + DECODE_SANYO_AC88 || DECODE_RHOSS || \ false) // Add any DECODE to the above if it uses result->state (see kStateSizeMax) // you might also want to add the protocol to hasACState function @@ -951,14 +972,19 @@ enum decode_type_t { TROTEC_3550, SANYO_AC88, // 105 BOSE, + ARRIS, + RHOSS, + AIRTON, // Add new entries before this one, and update it to point to the last entry. - kLastDecodeType = BOSE, + kLastDecodeType = AIRTON, }; // Message lengths & required repeat values const uint16_t kNoRepeat = 0; const uint16_t kSingleRepeat = 1; +const uint16_t kAirtonBits = 56; +const uint16_t kAirtonDefaultRepeat = kNoRepeat; const uint16_t kAirwellBits = 34; const uint16_t kAirwellMinRepeats = 2; const uint16_t kAiwaRcT501Bits = 15; @@ -970,6 +996,7 @@ const uint16_t kAmcorDefaultRepeat = kSingleRepeat; const uint16_t kArgoStateLength = 12; const uint16_t kArgoBits = kArgoStateLength * 8; const uint16_t kArgoDefaultRepeat = kNoRepeat; +const uint16_t kArrisBits = 32; const uint16_t kCoolixBits = 24; const uint16_t kCoolixDefaultRepeat = kSingleRepeat; const uint16_t kCarrierAcBits = 32; @@ -1195,6 +1222,9 @@ const uint16_t kMilesTag2ShotBits = 14; const uint16_t kMilesTag2MsgBits = 24; const uint16_t kMilesMinRepeat = 0; const uint16_t kBoseBits = 16; +const uint16_t kRhossStateLength = 12; +const uint16_t kRhossBits = kRhossStateLength * 8; +const uint16_t kRhossDefaultRepeat = 0; // Legacy defines. (Deprecated) diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRsend.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRsend.cpp index 4814bd431..e20b97045 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRsend.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRsend.cpp @@ -637,6 +637,7 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) { case LG: case LG2: return 28; + case ARRIS: case CARRIER_AC: case ELITESCREENS: case EPSON: @@ -665,6 +666,7 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) { case MIDEA: case PANASONIC: return 48; + case AIRTON: case ECOCLIM: case MAGIQUEST: case VESTEL_AC: @@ -738,6 +740,8 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) { return kNeoclimaBits; case PANASONIC_AC: return kPanasonicAcBits; + case RHOSS: + return kRhossBits; case SAMSUNG_AC: return kSamsungAcBits; case SANYO_AC: @@ -781,6 +785,11 @@ bool IRsend::send(const decode_type_t type, const uint64_t data, uint16_t min_repeat __attribute__((unused)) = std::max(IRsend::minRepeats(type), repeat); switch (type) { +#if SEND_AIRTON + case AIRTON: + sendAirton(data, nbits, min_repeat); + break; +#endif // SEND_AIRTON #if SEND_AIRWELL case AIRWELL: sendAirwell(data, nbits, min_repeat); @@ -790,7 +799,12 @@ bool IRsend::send(const decode_type_t type, const uint64_t data, case AIWA_RC_T501: sendAiwaRCT501(data, nbits, min_repeat); break; -#endif +#endif // SEND_AIWA_RC_T501 +#if SEND_ARRIS + case ARRIS: + sendArris(data, nbits, min_repeat); + break; +#endif // SEND_ARRIS #if SEND_BOSE case BOSE: sendBose(data, nbits, min_repeat); @@ -1247,6 +1261,11 @@ bool IRsend::send(const decode_type_t type, const uint8_t *state, sendPanasonicAC(state, nbytes); break; #endif // SEND_PANASONIC_AC +#if SEND_RHOSS + case RHOSS: + sendRhoss(state, nbytes); + break; +#endif // SEND_RHOSS #if SEND_SAMSUNG_AC case SAMSUNG_AC: sendSamsungAC(state, nbytes); diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRsend.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRsend.h index c20fc64bc..d55ce0238 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRsend.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRsend.h @@ -136,12 +136,24 @@ enum gree_ac_remote_model_t { YBOFB, // (2) Green, YBOFB2, YAPOF3 }; +/// HAIER_AC176 A/C model numbers +enum haier_ac176_remote_model_t { + V9014557_A = 1, // (1) V9014557 Remote in "A" setting. (Default) + V9014557_B, // (2) V9014557 Remote in "B" setting. +}; + /// HITACHI_AC1 A/C model numbers enum hitachi_ac1_remote_model_t { R_LT0541_HTA_A = 1, // (1) R-LT0541-HTA Remote in "A" setting. (Default) R_LT0541_HTA_B, // (2) R-LT0541-HTA Remote in "B" setting. }; +/// MIRAGE A/C model numbers +enum mirage_ac_remote_model_t { + KKG9AC1 = 1, // (1) KKG9A-C1 Remote. (Default) + KKG29AC1, // (2) KKG29A-C1 Remote. +}; + /// Panasonic A/C model numbers enum panasonic_ac_remote_model_t { kPanasonicUnknown = 0, @@ -160,6 +172,12 @@ enum sharp_ac_remote_model_t { A903 = 3, // 820 too }; +/// TCL A/C model numbers +enum tcl_ac_remote_model_t { + TAC09CHSD = 1, + GZ055BE1 = 2, +}; + /// Voltas A/C model numbers enum voltas_ac_remote_model_t { kVoltasUnknown = 0, // Full Function @@ -737,6 +755,21 @@ class IRsend { void sendBose(const uint64_t data, const uint16_t nbits = kBoseBits, const uint16_t repeat = kNoRepeat); #endif // SEND_BOSE +#if SEND_ARRIS + void sendArris(const uint64_t data, const uint16_t nbits = kArrisBits, + const uint16_t repeat = kNoRepeat); + static uint32_t toggleArrisRelease(const uint32_t data); + static uint32_t encodeArris(const uint32_t command, const bool release); +#endif // SEND_ARRIS +#if SEND_RHOSS + void sendRhoss(const unsigned char data[], + const uint16_t nbytes = kRhossStateLength, + const uint16_t repeat = kRhossDefaultRepeat); +#endif // SEND_RHOSS +#if SEND_AIRTON + void sendAirton(const uint64_t data, const uint16_t nbits = kAirtonBits, + const uint16_t repeat = kAirtonDefaultRepeat); +#endif // SEND_AIRTON protected: #ifdef UNIT_TEST diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRtext.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRtext.cpp index a7bd7de29..a580bff9f 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRtext.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRtext.cpp @@ -1,9 +1,10 @@ -// Copyright 2019-2020 - David Conran (@crankyoldgit) +// Copyright 2019-2021 - David Conran (@crankyoldgit) /// @file IRtext.cpp /// @warning If you add or remove an entry in this file, you should run: /// '../tools/generate_irtext_h.sh' to rebuild the `IRtext.h` file. +#include "IRtext.h" #ifndef UNIT_TEST #include #endif // UNIT_TEST @@ -14,178 +15,263 @@ #define PROGMEM // Pretend we have the PROGMEM macro even if we really don't. #endif +#ifndef FPSTR +#define FPSTR(X) X // Also pretend we have flash-string helper class cast. +#endif + +#define IRTEXT_CONST_BLOB_NAME(NAME)\ + NAME ## Blob + +#define IRTEXT_CONST_BLOB_DECL(NAME)\ + const char IRTEXT_CONST_BLOB_NAME(NAME) [] PROGMEM + +#define IRTEXT_CONST_BLOB_PTR(NAME)\ + IRTEXT_CONST_PTR(NAME) {\ + IRTEXT_CONST_PTR_CAST(IRTEXT_CONST_BLOB_NAME(NAME)) } + +#define IRTEXT_CONST_STRING(NAME, VALUE)\ + static IRTEXT_CONST_BLOB_DECL(NAME) { VALUE };\ + IRTEXT_CONST_PTR(NAME) PROGMEM {\ + IRTEXT_CONST_PTR_CAST(&(IRTEXT_CONST_BLOB_NAME(NAME))[0]) } + // Common -const PROGMEM char* kUnknownStr = D_STR_UNKNOWN; ///< "Unknown" -const PROGMEM char* kProtocolStr = D_STR_PROTOCOL; ///< "Protocol" -const PROGMEM char* kPowerStr = D_STR_POWER; ///< "Power" -const PROGMEM char* kOnStr = D_STR_ON; ///< "On" -const PROGMEM char* kOffStr = D_STR_OFF; ///< "Off" -const PROGMEM char* kModeStr = D_STR_MODE; ///< "Mode" -const PROGMEM char* kToggleStr = D_STR_TOGGLE; ///< "Toggle" -const PROGMEM char* kTurboStr = D_STR_TURBO; ///< "Turbo" -const PROGMEM char* kSuperStr = D_STR_SUPER; ///< "Super" -const PROGMEM char* kSleepStr = D_STR_SLEEP; ///< "Sleep" -const PROGMEM char* kLightStr = D_STR_LIGHT; ///< "Light" -const PROGMEM char* kPowerfulStr = D_STR_POWERFUL; ///< "Powerful" -const PROGMEM char* kQuietStr = D_STR_QUIET; ///< "Quiet" -const PROGMEM char* kEconoStr = D_STR_ECONO; ///< "Econo" -const PROGMEM char* kSwingStr = D_STR_SWING; ///< "Swing" -const PROGMEM char* kSwingHStr = D_STR_SWINGH; ///< "SwingH" -const PROGMEM char* kSwingVStr = D_STR_SWINGV; ///< "SwingV" -const PROGMEM char* kBeepStr = D_STR_BEEP; ///< "Beep" -const PROGMEM char* kZoneFollowStr = D_STR_ZONEFOLLOW; ///< "Zone Follow" -const PROGMEM char* kFixedStr = D_STR_FIXED; ///< "Fixed" -const PROGMEM char* kMouldStr = D_STR_MOULD; ///< "Mould" -const PROGMEM char* kCleanStr = D_STR_CLEAN; ///< "Clean" -const PROGMEM char* kPurifyStr = D_STR_PURIFY; ///< "Purify" -const PROGMEM char* kTimerStr = D_STR_TIMER; ///< "Timer" -const PROGMEM char* kOnTimerStr = D_STR_ONTIMER; ///< "On Timer" -const PROGMEM char* kOffTimerStr = D_STR_OFFTIMER; ///< "Off Timer" -const PROGMEM char* kTimerModeStr = D_STR_TIMERMODE; ///< "Timer Mode" -const PROGMEM char* kClockStr = D_STR_CLOCK; ///< "Clock" -const PROGMEM char* kCommandStr = D_STR_COMMAND; ///< "Command" -const PROGMEM char* kXFanStr = D_STR_XFAN; ///< "XFan" -const PROGMEM char* kHealthStr = D_STR_HEALTH; ///< "Health" -const PROGMEM char* kModelStr = D_STR_MODEL; ///< "Model" -const PROGMEM char* kTempStr = D_STR_TEMP; ///< "Temp" -const PROGMEM char* kIFeelStr = D_STR_IFEEL; ///< "IFeel" -const PROGMEM char* kHumidStr = D_STR_HUMID; ///< "Humid" -const PROGMEM char* kSaveStr = D_STR_SAVE; ///< "Save" -const PROGMEM char* kEyeStr = D_STR_EYE; ///< "Eye" -const PROGMEM char* kFollowStr = D_STR_FOLLOW; ///< "Follow" -const PROGMEM char* kIonStr = D_STR_ION; ///< "Ion" -const PROGMEM char* kFreshStr = D_STR_FRESH; ///< "Fresh" -const PROGMEM char* kHoldStr = D_STR_HOLD; ///< "Hold" -const PROGMEM char* kButtonStr = D_STR_BUTTON; ///< "Button" -const PROGMEM char* k8CHeatStr = D_STR_8C_HEAT; ///< "8C Heat" -const PROGMEM char* k10CHeatStr = D_STR_10C_HEAT; ///< "10C Heat" -const PROGMEM char* kNightStr = D_STR_NIGHT; ///< "Night" -const PROGMEM char* kSilentStr = D_STR_SILENT; ///< "Silent" -const PROGMEM char* kFilterStr = D_STR_FILTER; ///< "Filter" -const PROGMEM char* k3DStr = D_STR_3D; ///< "3D" -const PROGMEM char* kCelsiusStr = D_STR_CELSIUS; ///< "Celsius" -const PROGMEM char* kCelsiusFahrenheitStr = D_STR_CELSIUS_FAHRENHEIT; ///< +IRTEXT_CONST_STRING(kUnknownStr, D_STR_UNKNOWN); ///< "Unknown" +IRTEXT_CONST_STRING(kProtocolStr, D_STR_PROTOCOL); ///< "Protocol" +IRTEXT_CONST_STRING(kPowerStr, D_STR_POWER); ///< "Power" +IRTEXT_CONST_STRING(kOnStr, D_STR_ON); ///< "On" +IRTEXT_CONST_STRING(kOffStr, D_STR_OFF); ///< "Off" +IRTEXT_CONST_STRING(k1Str, D_STR_1); ///< "1" +IRTEXT_CONST_STRING(k0Str, D_STR_0); ///< "0" +IRTEXT_CONST_STRING(kModeStr, D_STR_MODE); ///< "Mode" +IRTEXT_CONST_STRING(kToggleStr, D_STR_TOGGLE); ///< "Toggle" +IRTEXT_CONST_STRING(kTurboStr, D_STR_TURBO); ///< "Turbo" +IRTEXT_CONST_STRING(kSuperStr, D_STR_SUPER); ///< "Super" +IRTEXT_CONST_STRING(kSleepStr, D_STR_SLEEP); ///< "Sleep" +IRTEXT_CONST_STRING(kLightStr, D_STR_LIGHT); ///< "Light" +IRTEXT_CONST_STRING(kPowerfulStr, D_STR_POWERFUL); ///< "Powerful" +IRTEXT_CONST_STRING(kQuietStr, D_STR_QUIET); ///< "Quiet" +IRTEXT_CONST_STRING(kEconoStr, D_STR_ECONO); ///< "Econo" +IRTEXT_CONST_STRING(kSwingStr, D_STR_SWING); ///< "Swing" +IRTEXT_CONST_STRING(kSwingHStr, D_STR_SWINGH); ///< "SwingH" +IRTEXT_CONST_STRING(kSwingVStr, D_STR_SWINGV); ///< "SwingV" +IRTEXT_CONST_STRING(kBeepStr, D_STR_BEEP); ///< "Beep" +IRTEXT_CONST_STRING(kZoneFollowStr, D_STR_ZONEFOLLOW); ///< "Zone Follow" +IRTEXT_CONST_STRING(kFixedStr, D_STR_FIXED); ///< "Fixed" +IRTEXT_CONST_STRING(kMouldStr, D_STR_MOULD); ///< "Mould" +IRTEXT_CONST_STRING(kCleanStr, D_STR_CLEAN); ///< "Clean" +IRTEXT_CONST_STRING(kPurifyStr, D_STR_PURIFY); ///< "Purify" +IRTEXT_CONST_STRING(kTimerStr, D_STR_TIMER); ///< "Timer" +IRTEXT_CONST_STRING(kOnTimerStr, D_STR_ONTIMER); ///< "On Timer" +IRTEXT_CONST_STRING(kOffTimerStr, D_STR_OFFTIMER); ///< "Off Timer" +IRTEXT_CONST_STRING(kTimerModeStr, D_STR_TIMERMODE); ///< "Timer Mode" +IRTEXT_CONST_STRING(kClockStr, D_STR_CLOCK); ///< "Clock" +IRTEXT_CONST_STRING(kCommandStr, D_STR_COMMAND); ///< "Command" +IRTEXT_CONST_STRING(kXFanStr, D_STR_XFAN); ///< "XFan" +IRTEXT_CONST_STRING(kHealthStr, D_STR_HEALTH); ///< "Health" +IRTEXT_CONST_STRING(kModelStr, D_STR_MODEL); ///< "Model" +IRTEXT_CONST_STRING(kTempStr, D_STR_TEMP); ///< "Temp" +IRTEXT_CONST_STRING(kIFeelStr, D_STR_IFEEL); ///< "IFeel" +IRTEXT_CONST_STRING(kHumidStr, D_STR_HUMID); ///< "Humid" +IRTEXT_CONST_STRING(kSaveStr, D_STR_SAVE); ///< "Save" +IRTEXT_CONST_STRING(kEyeStr, D_STR_EYE); ///< "Eye" +IRTEXT_CONST_STRING(kFollowStr, D_STR_FOLLOW); ///< "Follow" +IRTEXT_CONST_STRING(kIonStr, D_STR_ION); ///< "Ion" +IRTEXT_CONST_STRING(kFreshStr, D_STR_FRESH); ///< "Fresh" +IRTEXT_CONST_STRING(kHoldStr, D_STR_HOLD); ///< "Hold" +IRTEXT_CONST_STRING(kButtonStr, D_STR_BUTTON); ///< "Button" +IRTEXT_CONST_STRING(k8CHeatStr, D_STR_8C_HEAT); ///< "8C Heat" +IRTEXT_CONST_STRING(k10CHeatStr, D_STR_10C_HEAT); ///< "10C Heat" +IRTEXT_CONST_STRING(kNightStr, D_STR_NIGHT); ///< "Night" +IRTEXT_CONST_STRING(kSilentStr, D_STR_SILENT); ///< "Silent" +IRTEXT_CONST_STRING(kFilterStr, D_STR_FILTER); ///< "Filter" +IRTEXT_CONST_STRING(k3DStr, D_STR_3D); ///< "3D" +IRTEXT_CONST_STRING(kCelsiusStr, D_STR_CELSIUS); ///< "Celsius" +IRTEXT_CONST_STRING(kCelsiusFahrenheitStr, D_STR_CELSIUS_FAHRENHEIT); ///< ///< "Celsius/Fahrenheit" -const PROGMEM char* kTempUpStr = D_STR_TEMPUP; ///< "Temp Up" -const PROGMEM char* kTempDownStr = D_STR_TEMPDOWN; ///< "Temp Down" -const PROGMEM char* kStartStr = D_STR_START; ///< "Start" -const PROGMEM char* kStopStr = D_STR_STOP; ///< "Stop" -const PROGMEM char* kMoveStr = D_STR_MOVE; ///< "Move" -const PROGMEM char* kSetStr = D_STR_SET; ///< "Set" -const PROGMEM char* kCancelStr = D_STR_CANCEL; ///< "Cancel" -const PROGMEM char* kUpStr = D_STR_UP; ///< "Up" -const PROGMEM char* kDownStr = D_STR_DOWN; ///< "Down" -const PROGMEM char* kChangeStr = D_STR_CHANGE; ///< "Change" -const PROGMEM char* kComfortStr = D_STR_COMFORT; ///< "Comfort" -const PROGMEM char* kSensorStr = D_STR_SENSOR; ///< "Sensor" -const PROGMEM char* kWeeklyTimerStr = D_STR_WEEKLYTIMER; ///< "WeeklyTimer" -const PROGMEM char* kWifiStr = D_STR_WIFI; ///< "Wifi" -const PROGMEM char* kLastStr = D_STR_LAST; ///< "Last" -const PROGMEM char* kFastStr = D_STR_FAST; ///< "Fast" -const PROGMEM char* kSlowStr = D_STR_SLOW; ///< "Slow" -const PROGMEM char* kAirFlowStr = D_STR_AIRFLOW; ///< "Air Flow" -const PROGMEM char* kStepStr = D_STR_STEP; ///< "Step" -const PROGMEM char* kNAStr = D_STR_NA; ///< "N/A" -const PROGMEM char* kInsideStr = D_STR_INSIDE; ///< "Inside" -const PROGMEM char* kOutsideStr = D_STR_OUTSIDE; ///< "Outside" -const PROGMEM char* kLoudStr = D_STR_LOUD; ///< "Loud" -const PROGMEM char* kLowerStr = D_STR_LOWER; ///< "Lower" -const PROGMEM char* kUpperStr = D_STR_UPPER; ///< "Upper" -const PROGMEM char* kBreezeStr = D_STR_BREEZE; ///< "Breeze" -const PROGMEM char* kCirculateStr = D_STR_CIRCULATE; ///< "Circulate" -const PROGMEM char* kCeilingStr = D_STR_CEILING; ///< "Ceiling" -const PROGMEM char* kWallStr = D_STR_WALL; ///< "Wall" -const PROGMEM char* kRoomStr = D_STR_ROOM; ///< "Room" -const PROGMEM char* k6thSenseStr = D_STR_6THSENSE; ///< "6th Sense" -const PROGMEM char* kTypeStr = D_STR_TYPE; ///< "Type" -const PROGMEM char* kSpecialStr = D_STR_SPECIAL; ///< "Special" -const PROGMEM char* kIdStr = D_STR_ID; ///< "Id" / Device Identifier -const PROGMEM char* kVaneStr = D_STR_VANE; ///< "Vane" +IRTEXT_CONST_STRING(kTempUpStr, D_STR_TEMPUP); ///< "Temp Up" +IRTEXT_CONST_STRING(kTempDownStr, D_STR_TEMPDOWN); ///< "Temp Down" +IRTEXT_CONST_STRING(kStartStr, D_STR_START); ///< "Start" +IRTEXT_CONST_STRING(kStopStr, D_STR_STOP); ///< "Stop" +IRTEXT_CONST_STRING(kMoveStr, D_STR_MOVE); ///< "Move" +IRTEXT_CONST_STRING(kSetStr, D_STR_SET); ///< "Set" +IRTEXT_CONST_STRING(kCancelStr, D_STR_CANCEL); ///< "Cancel" +IRTEXT_CONST_STRING(kUpStr, D_STR_UP); ///< "Up" +IRTEXT_CONST_STRING(kDownStr, D_STR_DOWN); ///< "Down" +IRTEXT_CONST_STRING(kChangeStr, D_STR_CHANGE); ///< "Change" +IRTEXT_CONST_STRING(kComfortStr, D_STR_COMFORT); ///< "Comfort" +IRTEXT_CONST_STRING(kSensorStr, D_STR_SENSOR); ///< "Sensor" +IRTEXT_CONST_STRING(kWeeklyTimerStr, D_STR_WEEKLYTIMER); ///< "WeeklyTimer" +IRTEXT_CONST_STRING(kWifiStr, D_STR_WIFI); ///< "Wifi" +IRTEXT_CONST_STRING(kLastStr, D_STR_LAST); ///< "Last" +IRTEXT_CONST_STRING(kFastStr, D_STR_FAST); ///< "Fast" +IRTEXT_CONST_STRING(kSlowStr, D_STR_SLOW); ///< "Slow" +IRTEXT_CONST_STRING(kAirFlowStr, D_STR_AIRFLOW); ///< "Air Flow" +IRTEXT_CONST_STRING(kStepStr, D_STR_STEP); ///< "Step" +IRTEXT_CONST_STRING(kNAStr, D_STR_NA); ///< "N/A" +IRTEXT_CONST_STRING(kInsideStr, D_STR_INSIDE); ///< "Inside" +IRTEXT_CONST_STRING(kOutsideStr, D_STR_OUTSIDE); ///< "Outside" +IRTEXT_CONST_STRING(kLoudStr, D_STR_LOUD); ///< "Loud" +IRTEXT_CONST_STRING(kLowerStr, D_STR_LOWER); ///< "Lower" +IRTEXT_CONST_STRING(kUpperStr, D_STR_UPPER); ///< "Upper" +IRTEXT_CONST_STRING(kBreezeStr, D_STR_BREEZE); ///< "Breeze" +IRTEXT_CONST_STRING(kCirculateStr, D_STR_CIRCULATE); ///< "Circulate" +IRTEXT_CONST_STRING(kCeilingStr, D_STR_CEILING); ///< "Ceiling" +IRTEXT_CONST_STRING(kWallStr, D_STR_WALL); ///< "Wall" +IRTEXT_CONST_STRING(kRoomStr, D_STR_ROOM); ///< "Room" +IRTEXT_CONST_STRING(k6thSenseStr, D_STR_6THSENSE); ///< "6th Sense" +IRTEXT_CONST_STRING(kTypeStr, D_STR_TYPE); ///< "Type" +IRTEXT_CONST_STRING(kSpecialStr, D_STR_SPECIAL); ///< "Special" +IRTEXT_CONST_STRING(kIdStr, D_STR_ID); ///< "Id" / Device Identifier +IRTEXT_CONST_STRING(kVaneStr, D_STR_VANE); ///< "Vane" +IRTEXT_CONST_STRING(kLockStr, D_STR_LOCK); ///< "Lock" -const PROGMEM char* kAutoStr = D_STR_AUTO; ///< "Auto" -const PROGMEM char* kAutomaticStr = D_STR_AUTOMATIC; ///< "Automatic" -const PROGMEM char* kManualStr = D_STR_MANUAL; ///< "Manual" -const PROGMEM char* kCoolStr = D_STR_COOL; ///< "Cool" -const PROGMEM char* kHeatStr = D_STR_HEAT; ///< "Heat" -const PROGMEM char* kFanStr = D_STR_FAN; ///< "Fan" -const PROGMEM char* kDryStr = D_STR_DRY; ///< "Dry" -const PROGMEM char* kFanOnlyStr = D_STR_FANONLY; ///< "fan_only" -const PROGMEM char* kRecycleStr = D_STR_RECYCLE; ///< "Recycle" +IRTEXT_CONST_STRING(kAutoStr, D_STR_AUTO); ///< "Auto" +IRTEXT_CONST_STRING(kAutomaticStr, D_STR_AUTOMATIC); ///< "Automatic" +IRTEXT_CONST_STRING(kManualStr, D_STR_MANUAL); ///< "Manual" +IRTEXT_CONST_STRING(kCoolStr, D_STR_COOL); ///< "Cool" +IRTEXT_CONST_STRING(kCoolingStr, D_STR_COOLING); ///< "Cooling" +IRTEXT_CONST_STRING(kHeatStr, D_STR_HEAT); ///< "Heat" +IRTEXT_CONST_STRING(kHeatingStr, D_STR_HEATING); ///< "Heating" +IRTEXT_CONST_STRING(kDryStr, D_STR_DRY); ///< "Dry" +IRTEXT_CONST_STRING(kDryingStr, D_STR_DRYING); ///< "Drying" +IRTEXT_CONST_STRING(kDehumidifyStr, D_STR_DEHUMIDIFY); ///< "Dehumidify" +IRTEXT_CONST_STRING(kFanStr, D_STR_FAN); ///< "Fan" +// The following Fans strings with "only" are required to help with +// HomeAssistant & Google Home Climate integration. For compatibility only. +// Ref: https://www.home-assistant.io/integrations/google_assistant/#climate-operation-modes +IRTEXT_CONST_STRING(kFanOnlyStr, D_STR_FANONLY); ///< "fan-only" +IRTEXT_CONST_STRING(kFan_OnlyStr, D_STR_FAN_ONLY); ///< "fan_only" (HA/legacy) +IRTEXT_CONST_STRING(kFanOnlyWithSpaceStr, D_STR_FANSPACEONLY); ///< "Fan Only" +IRTEXT_CONST_STRING(kFanOnlyNoSpaceStr, D_STR_FANONLYNOSPACE); ///< "FanOnly" -const PROGMEM char* kMaxStr = D_STR_MAX; ///< "Max" -const PROGMEM char* kMaximumStr = D_STR_MAXIMUM; ///< "Maximum" -const PROGMEM char* kMinStr = D_STR_MIN; ///< "Min" -const PROGMEM char* kMinimumStr = D_STR_MINIMUM; ///< "Minimum" -const PROGMEM char* kMedStr = D_STR_MED; ///< "Med" -const PROGMEM char* kMediumStr = D_STR_MEDIUM; ///< "Medium" +IRTEXT_CONST_STRING(kRecycleStr, D_STR_RECYCLE); ///< "Recycle" -const PROGMEM char* kHighestStr = D_STR_HIGHEST; ///< "Highest" -const PROGMEM char* kHighStr = D_STR_HIGH; ///< "High" -const PROGMEM char* kHiStr = D_STR_HI; ///< "Hi" -const PROGMEM char* kMidStr = D_STR_MID; ///< "Mid" -const PROGMEM char* kMiddleStr = D_STR_MIDDLE; ///< "Middle" -const PROGMEM char* kLowStr = D_STR_LOW; ///< "Low" -const PROGMEM char* kLoStr = D_STR_LO; ///< "Lo" -const PROGMEM char* kLowestStr = D_STR_LOWEST; ///< "Lowest" -const PROGMEM char* kMaxRightStr = D_STR_MAXRIGHT; ///< "Max Right" -const PROGMEM char* kRightMaxStr = D_STR_RIGHTMAX_NOSPACE; ///< "RightMax" -const PROGMEM char* kRightStr = D_STR_RIGHT; ///< "Right" -const PROGMEM char* kLeftStr = D_STR_LEFT; ///< "Left" -const PROGMEM char* kMaxLeftStr = D_STR_MAXLEFT; ///< "Max Left" -const PROGMEM char* kLeftMaxStr = D_STR_LEFTMAX_NOSPACE; ///< "LeftMax" -const PROGMEM char* kWideStr = D_STR_WIDE; ///< "Wide" -const PROGMEM char* kCentreStr = D_STR_CENTRE; ///< "Centre" -const PROGMEM char* kTopStr = D_STR_TOP; ///< "Top" -const PROGMEM char* kBottomStr = D_STR_BOTTOM; ///< "Bottom" +IRTEXT_CONST_STRING(kMaxStr, D_STR_MAX); ///< "Max" +IRTEXT_CONST_STRING(kMaximumStr, D_STR_MAXIMUM); ///< "Maximum" +IRTEXT_CONST_STRING(kMinStr, D_STR_MIN); ///< "Min" +IRTEXT_CONST_STRING(kMinimumStr, D_STR_MINIMUM); ///< "Minimum" +IRTEXT_CONST_STRING(kMedStr, D_STR_MED); ///< "Med" +IRTEXT_CONST_STRING(kMediumStr, D_STR_MEDIUM); ///< "Medium" + +IRTEXT_CONST_STRING(kHighestStr, D_STR_HIGHEST); ///< "Highest" +IRTEXT_CONST_STRING(kHighStr, D_STR_HIGH); ///< "High" +IRTEXT_CONST_STRING(kHiStr, D_STR_HI); ///< "Hi" +IRTEXT_CONST_STRING(kMidStr, D_STR_MID); ///< "Mid" +IRTEXT_CONST_STRING(kMiddleStr, D_STR_MIDDLE); ///< "Middle" +IRTEXT_CONST_STRING(kLowStr, D_STR_LOW); ///< "Low" +IRTEXT_CONST_STRING(kLoStr, D_STR_LO); ///< "Lo" +IRTEXT_CONST_STRING(kLowestStr, D_STR_LOWEST); ///< "Lowest" +IRTEXT_CONST_STRING(kMaxRightStr, D_STR_MAXRIGHT); ///< "Max Right" +IRTEXT_CONST_STRING(kMaxRightNoSpaceStr, D_STR_MAXRIGHT_NOSPACE); ///< + ///< "MaxRight" +IRTEXT_CONST_STRING(kRightMaxStr, D_STR_RIGHTMAX); ///< "Right Max" +IRTEXT_CONST_STRING(kRightMaxNoSpaceStr, D_STR_RIGHTMAX_NOSPACE); ///< + ///< "RightMax" +IRTEXT_CONST_STRING(kRightStr, D_STR_RIGHT); ///< "Right" +IRTEXT_CONST_STRING(kLeftStr, D_STR_LEFT); ///< "Left" +IRTEXT_CONST_STRING(kMaxLeftStr, D_STR_MAXLEFT); ///< "Max Left" +IRTEXT_CONST_STRING(kMaxLeftNoSpaceStr, D_STR_MAXLEFT_NOSPACE); ///< "MaxLeft" +IRTEXT_CONST_STRING(kLeftMaxStr, D_STR_LEFTMAX); ///< "Left Max" +IRTEXT_CONST_STRING(kLeftMaxNoSpaceStr, D_STR_LEFTMAX_NOSPACE); ///< "LeftMax" +IRTEXT_CONST_STRING(kWideStr, D_STR_WIDE); ///< "Wide" +IRTEXT_CONST_STRING(kCentreStr, D_STR_CENTRE); ///< "Centre" +IRTEXT_CONST_STRING(kTopStr, D_STR_TOP); ///< "Top" +IRTEXT_CONST_STRING(kBottomStr, D_STR_BOTTOM); ///< "Bottom" // Compound words/phrases/descriptions from pre-defined words. -const PROGMEM char* kEconoToggleStr = D_STR_ECONOTOGGLE; ///< "Econo Toggle" -const PROGMEM char* kEyeAutoStr = D_STR_EYEAUTO; ///< "Eye Auto" -const PROGMEM char* kLightToggleStr = D_STR_LIGHTTOGGLE; ///< "Light Toggle" -const PROGMEM char* kOutsideQuietStr = D_STR_OUTSIDEQUIET; ///< "Outside Quiet" -const PROGMEM char* kPowerToggleStr = D_STR_POWERTOGGLE; ///< "Power Toggle" -const PROGMEM char* kPowerButtonStr = D_STR_POWERBUTTON; ///< "Power Button" -const PROGMEM char* kPreviousPowerStr = D_STR_PREVIOUSPOWER; ///< +IRTEXT_CONST_STRING(kEconoToggleStr, D_STR_ECONOTOGGLE); ///< "Econo Toggle" +IRTEXT_CONST_STRING(kEyeAutoStr, D_STR_EYEAUTO); ///< "Eye Auto" +IRTEXT_CONST_STRING(kLightToggleStr, D_STR_LIGHTTOGGLE); ///< "Light Toggle" +///< "Outside Quiet" +IRTEXT_CONST_STRING(kOutsideQuietStr, D_STR_OUTSIDEQUIET); +IRTEXT_CONST_STRING(kPowerToggleStr, D_STR_POWERTOGGLE); ///< "Power Toggle" +IRTEXT_CONST_STRING(kPowerButtonStr, D_STR_POWERBUTTON); ///< "Power Button" +IRTEXT_CONST_STRING(kPreviousPowerStr, D_STR_PREVIOUSPOWER); ///< ///< "Previous Power" -const PROGMEM char* kDisplayTempStr = D_STR_DISPLAYTEMP; ///< "Display Temp" -const PROGMEM char* kSensorTempStr = D_STR_SENSORTEMP; ///< "Sensor Temp" -const PROGMEM char* kSleepTimerStr = D_STR_SLEEP_TIMER; ///< "Sleep Timer" -const PROGMEM char* kSwingVModeStr = D_STR_SWINGVMODE; ///< "Swing(V) Mode" -const PROGMEM char* kSwingVToggleStr = D_STR_SWINGVTOGGLE; ///< +IRTEXT_CONST_STRING(kDisplayTempStr, D_STR_DISPLAYTEMP); ///< "Display Temp" +IRTEXT_CONST_STRING(kSensorTempStr, D_STR_SENSORTEMP); ///< "Sensor Temp" +IRTEXT_CONST_STRING(kSleepTimerStr, D_STR_SLEEP_TIMER); ///< "Sleep Timer" +IRTEXT_CONST_STRING(kSwingVModeStr, D_STR_SWINGVMODE); ///< "Swing(V) Mode" +IRTEXT_CONST_STRING(kSwingVToggleStr, D_STR_SWINGVTOGGLE); ///< ///< "Swing(V) Toggle" -const PROGMEM char* kTurboToggleStr = D_STR_TURBOTOGGLE; ///< "Turbo Toggle" +IRTEXT_CONST_STRING(kTurboToggleStr, D_STR_TURBOTOGGLE); ///< "Turbo Toggle" -// Separators -char kTimeSep = D_CHR_TIME_SEP; ///< ':' -const PROGMEM char* kSpaceLBraceStr = D_STR_SPACELBRACE; ///< " (" -const PROGMEM char* kCommaSpaceStr = D_STR_COMMASPACE; ///< ", " -const PROGMEM char* kColonSpaceStr = D_STR_COLONSPACE; ///< ": " +// Separators & Punctuation +const char kTimeSep = D_CHR_TIME_SEP; ///< ':' +IRTEXT_CONST_STRING(kSpaceLBraceStr, D_STR_SPACELBRACE); ///< " (" +IRTEXT_CONST_STRING(kCommaSpaceStr, D_STR_COMMASPACE); ///< ", " +IRTEXT_CONST_STRING(kColonSpaceStr, D_STR_COLONSPACE); ///< ": " +IRTEXT_CONST_STRING(kDashStr, D_STR_DASH); ///< "-" // IRutils // - Time -const PROGMEM char* kDayStr = D_STR_DAY; ///< "Day" -const PROGMEM char* kDaysStr = D_STR_DAYS; ///< "Days" -const PROGMEM char* kHourStr = D_STR_HOUR; ///< "Hour" -const PROGMEM char* kHoursStr = D_STR_HOURS; ///< "Hours" -const PROGMEM char* kMinuteStr = D_STR_MINUTE; ///< "Minute" -const PROGMEM char* kMinutesStr = D_STR_MINUTES; ///< "Minutes" -const PROGMEM char* kSecondStr = D_STR_SECOND; ///< "Second" -const PROGMEM char* kSecondsStr = D_STR_SECONDS; ///< "Seconds" -const PROGMEM char* kNowStr = D_STR_NOW; ///< "Now" -const PROGMEM char* kThreeLetterDayOfWeekStr = D_STR_THREELETTERDAYS; ///< +IRTEXT_CONST_STRING(kDayStr, D_STR_DAY); ///< "Day" +IRTEXT_CONST_STRING(kDaysStr, D_STR_DAYS); ///< "Days" +IRTEXT_CONST_STRING(kHourStr, D_STR_HOUR); ///< "Hour" +IRTEXT_CONST_STRING(kHoursStr, D_STR_HOURS); ///< "Hours" +IRTEXT_CONST_STRING(kMinuteStr, D_STR_MINUTE); ///< "Minute" +IRTEXT_CONST_STRING(kMinutesStr, D_STR_MINUTES); ///< "Minutes" +IRTEXT_CONST_STRING(kSecondStr, D_STR_SECOND); ///< "Second" +IRTEXT_CONST_STRING(kSecondsStr, D_STR_SECONDS); ///< "Seconds" +IRTEXT_CONST_STRING(kNowStr, D_STR_NOW); ///< "Now" +IRTEXT_CONST_STRING(kThreeLetterDayOfWeekStr, D_STR_THREELETTERDAYS); ///< ///< "SunMonTueWedThuFriSat" -const PROGMEM char* kYesStr = D_STR_YES; ///< "Yes" -const PROGMEM char* kNoStr = D_STR_NO; ///< "No" -const PROGMEM char* kTrueStr = D_STR_TRUE; ///< "True" -const PROGMEM char* kFalseStr = D_STR_FALSE; ///< "False" +IRTEXT_CONST_STRING(kYesStr, D_STR_YES); ///< "Yes" +IRTEXT_CONST_STRING(kNoStr, D_STR_NO); ///< "No" +IRTEXT_CONST_STRING(kTrueStr, D_STR_TRUE); ///< "True" +IRTEXT_CONST_STRING(kFalseStr, D_STR_FALSE); ///< "False" -const PROGMEM char* kRepeatStr = D_STR_REPEAT; ///< "Repeat" -const PROGMEM char* kCodeStr = D_STR_CODE; ///< "Code" -const PROGMEM char* kBitsStr = D_STR_BITS; ///< "Bits" +IRTEXT_CONST_STRING(kRepeatStr, D_STR_REPEAT); ///< "Repeat" +IRTEXT_CONST_STRING(kCodeStr, D_STR_CODE); ///< "Code" +IRTEXT_CONST_STRING(kBitsStr, D_STR_BITS); ///< "Bits" + +// Model Names +IRTEXT_CONST_STRING(kYaw1fStr, D_STR_YAW1F); ///< "YAW1F" +IRTEXT_CONST_STRING(kYbofbStr, D_STR_YBOFB); ///< "YBOFB" +IRTEXT_CONST_STRING(kV9014557AStr, D_STR_V9014557_A); ///< "V9014557-A" +IRTEXT_CONST_STRING(kV9014557BStr, D_STR_V9014557_B); ///< "V9014557-B" +IRTEXT_CONST_STRING(kRlt0541htaaStr, D_STR_RLT0541HTA_A); ///< "R-LT0541-HTA-A" +IRTEXT_CONST_STRING(kRlt0541htabStr, D_STR_RLT0541HTA_B); ///< "R-LT0541-HTA-B" +IRTEXT_CONST_STRING(kArrah2eStr, D_STR_ARRAH2E); ///< "ARRAH2E" +IRTEXT_CONST_STRING(kArdb1Str, D_STR_ARDB1); ///< "ARDB1" +IRTEXT_CONST_STRING(kArreb1eStr, D_STR_ARREB1E); ///< "ARREB1E" +IRTEXT_CONST_STRING(kArjw2Str, D_STR_ARJW2); ///< "ARJW2" +IRTEXT_CONST_STRING(kArry4Str, D_STR_ARRY4); ///< "ARRY4" +IRTEXT_CONST_STRING(kArrew4eStr, D_STR_ARREW4E); ///< "ARREW4E" +IRTEXT_CONST_STRING(kGe6711ar2853mStr, D_STR_GE6711AR2853M); ///< + ///< "GE6711AR2853M" +IRTEXT_CONST_STRING(kAkb75215403Str, D_STR_AKB75215403); ///< "AKB75215403" +IRTEXT_CONST_STRING(kAkb74955603Str, D_STR_AKB74955603); ///< "AKB74955603" +IRTEXT_CONST_STRING(kAkb73757604Str, D_STR_AKB73757604); ///< "AKB73757604" +IRTEXT_CONST_STRING(kKkg9ac1Str, D_STR_KKG9AC1); ///< "KKG9AC1" +IRTEXT_CONST_STRING(kKkg29ac1Str, D_STR_KKG29AC1); ///< "KKG29AC1" +IRTEXT_CONST_STRING(kLkeStr, D_STR_LKE); ///< "LKE" +IRTEXT_CONST_STRING(kNkeStr, D_STR_NKE); ///< "NKE" +IRTEXT_CONST_STRING(kDkeStr, D_STR_DKE); ///< "DKE" +IRTEXT_CONST_STRING(kPkrStr, D_STR_PKR); ///< "PKR" +IRTEXT_CONST_STRING(kJkeStr, D_STR_JKE); ///< "JKE" +IRTEXT_CONST_STRING(kCkpStr, D_STR_CKP); ///< "CKP" +IRTEXT_CONST_STRING(kRkrStr, D_STR_RKR); ///< "RKR" +IRTEXT_CONST_STRING(kPanasonicLkeStr, D_STR_PANASONICLKE); ///< "PANASONICLKE" +IRTEXT_CONST_STRING(kPanasonicNkeStr, D_STR_PANASONICNKE); ///< "PANASONICNKE" +IRTEXT_CONST_STRING(kPanasonicDkeStr, D_STR_PANASONICDKE); ///< "PANASONICDKE" +IRTEXT_CONST_STRING(kPanasonicPkrStr, D_STR_PANASONICPKR); ///< "PANASONICPKR" +IRTEXT_CONST_STRING(kPanasonicJkeStr, D_STR_PANASONICJKE); ///< "PANASONICJKE" +IRTEXT_CONST_STRING(kPanasonicCkpStr, D_STR_PANASONICCKP); ///< "PANASONICCKP" +IRTEXT_CONST_STRING(kPanasonicRkrStr, D_STR_PANASONICRKR); ///< "PANASONICRKR" +IRTEXT_CONST_STRING(kA907Str, D_STR_A907); ///< "A907" +IRTEXT_CONST_STRING(kA705Str, D_STR_A705); ///< "A705" +IRTEXT_CONST_STRING(kA903Str, D_STR_A903); ///< "A903" +IRTEXT_CONST_STRING(kTac09chsdStr, D_STR_TAC09CHSD); ///< "TAC09CHSD" +IRTEXT_CONST_STRING(kGz055be1Str, D_STR_GZ055BE1); ///< "GZ055BE1" +IRTEXT_CONST_STRING(k122lzfStr, D_STR_122LZF); ///< "122LZF" +IRTEXT_CONST_STRING(kDg11j13aStr, D_STR_DG11J13A); ///< "DG11J13A" +IRTEXT_CONST_STRING(kDg11j104Str, D_STR_DG11J104); ///< "DG11J104" +IRTEXT_CONST_STRING(kDg11j191Str, D_STR_DG11J191); ///< "DG11J191" // Protocol Names // Needs to be in decode_type_t order. -const PROGMEM char *kAllProtocolNamesStr = +IRTEXT_CONST_BLOB_DECL(kAllProtocolNamesStr) { D_STR_UNUSED "\x0" D_STR_RC5 "\x0" D_STR_RC6 "\x0" @@ -293,5 +379,11 @@ const PROGMEM char *kAllProtocolNamesStr = D_STR_TROTEC_3550 "\x0" D_STR_SANYO_AC88 "\x0" D_STR_BOSE "\x0" + D_STR_ARRIS "\x0" + D_STR_RHOSS "\x0" + D_STR_AIRTON "\x0" ///< New protocol strings should be added just above this line. - "\x0"; ///< This string requires double null termination. + "\x0" ///< This string requires double null termination. +}; + +IRTEXT_CONST_BLOB_PTR(kAllProtocolNamesStr); diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRtext.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRtext.h index 55840688d..ee8ea5934 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRtext.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRtext.h @@ -12,158 +12,224 @@ // Constant text to be shared across all object files. // This means there is only one copy of the character/string/text etc. -extern char kTimeSep; -extern const char* k10CHeatStr; -extern const char* k3DStr; -extern const char* k6thSenseStr; -extern const char* k8CHeatStr; -extern const char* kAirFlowStr; -extern const char *kAllProtocolNamesStr; -extern const char* kAutomaticStr; -extern const char* kAutoStr; -extern const char* kBeepStr; -extern const char* kBitsStr; -extern const char* kBottomStr; -extern const char* kBreezeStr; -extern const char* kButtonStr; -extern const char* kCancelStr; -extern const char* kCeilingStr; -extern const char* kCelsiusFahrenheitStr; -extern const char* kCelsiusStr; -extern const char* kCentreStr; -extern const char* kChangeStr; -extern const char* kCirculateStr; -extern const char* kCleanStr; -extern const char* kClockStr; -extern const char* kCodeStr; -extern const char* kColonSpaceStr; -extern const char* kComfortStr; -extern const char* kCommandStr; -extern const char* kCommaSpaceStr; -extern const char* kCoolStr; -extern const char* kDaysStr; -extern const char* kDayStr; -extern const char* kDisplayTempStr; -extern const char* kDownStr; -extern const char* kDryStr; -extern const char* kEconoStr; -extern const char* kEconoToggleStr; -extern const char* kEyeAutoStr; -extern const char* kEyeStr; -extern const char* kFalseStr; -extern const char* kFanOnlyStr; -extern const char* kFanStr; -extern const char* kFastStr; -extern const char* kFilterStr; -extern const char* kFixedStr; -extern const char* kFollowStr; -extern const char* kFreshStr; -extern const char* kHealthStr; -extern const char* kHeatStr; -extern const char* kHighestStr; -extern const char* kHighStr; -extern const char* kHiStr; -extern const char* kHoldStr; -extern const char* kHoursStr; -extern const char* kHourStr; -extern const char* kHumidStr; -extern const char* kIdStr; -extern const char* kIFeelStr; -extern const char* kInsideStr; -extern const char* kIonStr; -extern const char* kLastStr; -extern const char* kLeftMaxStr; -extern const char* kLeftStr; -extern const char* kLightStr; -extern const char* kLightToggleStr; -extern const char* kLoStr; -extern const char* kLoudStr; -extern const char* kLowerStr; -extern const char* kLowestStr; -extern const char* kLowStr; -extern const char* kManualStr; -extern const char* kMaximumStr; -extern const char* kMaxLeftStr; -extern const char* kMaxRightStr; -extern const char* kMaxStr; -extern const char* kMediumStr; -extern const char* kMedStr; -extern const char* kMiddleStr; -extern const char* kMidStr; -extern const char* kMinimumStr; -extern const char* kMinStr; -extern const char* kMinutesStr; -extern const char* kMinuteStr; -extern const char* kModelStr; -extern const char* kModeStr; -extern const char* kMouldStr; -extern const char* kMoveStr; -extern const char* kNAStr; -extern const char* kNightStr; -extern const char* kNoStr; -extern const char* kNowStr; -extern const char* kOffStr; -extern const char* kOffTimerStr; -extern const char* kOnStr; -extern const char* kOnTimerStr; -extern const char* kOutsideQuietStr; -extern const char* kOutsideStr; -extern const char* kPowerButtonStr; -extern const char* kPowerfulStr; -extern const char* kPowerStr; -extern const char* kPowerToggleStr; -extern const char* kPreviousPowerStr; -extern const char* kProtocolStr; -extern const char* kPurifyStr; -extern const char* kQuietStr; -extern const char* kRecycleStr; -extern const char* kRepeatStr; -extern const char* kRightMaxStr; -extern const char* kRightStr; -extern const char* kRoomStr; -extern const char* kSaveStr; -extern const char* kSecondsStr; -extern const char* kSecondStr; -extern const char* kSensorStr; -extern const char* kSensorTempStr; -extern const char* kSetStr; -extern const char* kSilentStr; -extern const char* kSleepStr; -extern const char* kSleepTimerStr; -extern const char* kSlowStr; -extern const char* kSpaceLBraceStr; -extern const char* kSpecialStr; -extern const char* kStartStr; -extern const char* kStepStr; -extern const char* kStopStr; -extern const char* kSuperStr; -extern const char* kSwingHStr; -extern const char* kSwingStr; -extern const char* kSwingVModeStr; -extern const char* kSwingVStr; -extern const char* kSwingVToggleStr; -extern const char* kTempDownStr; -extern const char* kTempStr; -extern const char* kTempUpStr; -extern const char* kThreeLetterDayOfWeekStr; -extern const char* kTimerModeStr; -extern const char* kTimerStr; -extern const char* kToggleStr; -extern const char* kTopStr; -extern const char* kTrueStr; -extern const char* kTurboStr; -extern const char* kTurboToggleStr; -extern const char* kTypeStr; -extern const char* kUnknownStr; -extern const char* kUpperStr; -extern const char* kUpStr; -extern const char* kVaneStr; -extern const char* kWallStr; -extern const char* kWeeklyTimerStr; -extern const char* kWideStr; -extern const char* kWifiStr; -extern const char* kXFanStr; -extern const char* kYesStr; -extern const char* kZoneFollowStr; +#ifdef ESP8266 +class __FlashStringHelper; +#define IRTEXT_CONST_PTR_CAST(PTR)\ + reinterpret_cast(PTR) +#define IRTEXT_CONST_PTR(NAME) const __FlashStringHelper* const NAME +#else // ESP8266 +#define IRTEXT_CONST_PTR_CAST(PTR) PTR +#define IRTEXT_CONST_PTR(NAME) const char* const NAME +#endif // ESP8266 + +extern const char kTimeSep; +extern IRTEXT_CONST_PTR(k0Str); +extern IRTEXT_CONST_PTR(k10CHeatStr); +extern IRTEXT_CONST_PTR(k122lzfStr); +extern IRTEXT_CONST_PTR(k1Str); +extern IRTEXT_CONST_PTR(k3DStr); +extern IRTEXT_CONST_PTR(k6thSenseStr); +extern IRTEXT_CONST_PTR(k8CHeatStr); +extern IRTEXT_CONST_PTR(kA705Str); +extern IRTEXT_CONST_PTR(kA903Str); +extern IRTEXT_CONST_PTR(kA907Str); +extern IRTEXT_CONST_PTR(kAirFlowStr); +extern IRTEXT_CONST_PTR(kAkb73757604Str); +extern IRTEXT_CONST_PTR(kAkb74955603Str); +extern IRTEXT_CONST_PTR(kAkb75215403Str); +extern IRTEXT_CONST_PTR(kArdb1Str); +extern IRTEXT_CONST_PTR(kArjw2Str); +extern IRTEXT_CONST_PTR(kArrah2eStr); +extern IRTEXT_CONST_PTR(kArreb1eStr); +extern IRTEXT_CONST_PTR(kArrew4eStr); +extern IRTEXT_CONST_PTR(kArry4Str); +extern IRTEXT_CONST_PTR(kAutomaticStr); +extern IRTEXT_CONST_PTR(kAutoStr); +extern IRTEXT_CONST_PTR(kBeepStr); +extern IRTEXT_CONST_PTR(kBitsStr); +extern IRTEXT_CONST_PTR(kBottomStr); +extern IRTEXT_CONST_PTR(kBreezeStr); +extern IRTEXT_CONST_PTR(kButtonStr); +extern IRTEXT_CONST_PTR(kCancelStr); +extern IRTEXT_CONST_PTR(kCeilingStr); +extern IRTEXT_CONST_PTR(kCelsiusFahrenheitStr); +extern IRTEXT_CONST_PTR(kCelsiusStr); +extern IRTEXT_CONST_PTR(kCentreStr); +extern IRTEXT_CONST_PTR(kChangeStr); +extern IRTEXT_CONST_PTR(kCirculateStr); +extern IRTEXT_CONST_PTR(kCkpStr); +extern IRTEXT_CONST_PTR(kCleanStr); +extern IRTEXT_CONST_PTR(kClockStr); +extern IRTEXT_CONST_PTR(kCodeStr); +extern IRTEXT_CONST_PTR(kColonSpaceStr); +extern IRTEXT_CONST_PTR(kComfortStr); +extern IRTEXT_CONST_PTR(kCommandStr); +extern IRTEXT_CONST_PTR(kCommaSpaceStr); +extern IRTEXT_CONST_PTR(kCoolingStr); +extern IRTEXT_CONST_PTR(kCoolStr); +extern IRTEXT_CONST_PTR(kDashStr); +extern IRTEXT_CONST_PTR(kDaysStr); +extern IRTEXT_CONST_PTR(kDayStr); +extern IRTEXT_CONST_PTR(kDehumidifyStr); +extern IRTEXT_CONST_PTR(kDg11j104Str); +extern IRTEXT_CONST_PTR(kDg11j13aStr); +extern IRTEXT_CONST_PTR(kDg11j191Str); +extern IRTEXT_CONST_PTR(kDisplayTempStr); +extern IRTEXT_CONST_PTR(kDkeStr); +extern IRTEXT_CONST_PTR(kDownStr); +extern IRTEXT_CONST_PTR(kDryingStr); +extern IRTEXT_CONST_PTR(kDryStr); +extern IRTEXT_CONST_PTR(kEconoStr); +extern IRTEXT_CONST_PTR(kEconoToggleStr); +extern IRTEXT_CONST_PTR(kEyeAutoStr); +extern IRTEXT_CONST_PTR(kEyeStr); +extern IRTEXT_CONST_PTR(kFalseStr); +extern IRTEXT_CONST_PTR(kFanOnlyNoSpaceStr); +extern IRTEXT_CONST_PTR(kFan_OnlyStr); +extern IRTEXT_CONST_PTR(kFanOnlyStr); +extern IRTEXT_CONST_PTR(kFanOnlyWithSpaceStr); +extern IRTEXT_CONST_PTR(kFanStr); +extern IRTEXT_CONST_PTR(kFastStr); +extern IRTEXT_CONST_PTR(kFilterStr); +extern IRTEXT_CONST_PTR(kFixedStr); +extern IRTEXT_CONST_PTR(kFollowStr); +extern IRTEXT_CONST_PTR(kFreshStr); +extern IRTEXT_CONST_PTR(kGe6711ar2853mStr); +extern IRTEXT_CONST_PTR(kGz055be1Str); +extern IRTEXT_CONST_PTR(kHealthStr); +extern IRTEXT_CONST_PTR(kHeatingStr); +extern IRTEXT_CONST_PTR(kHeatStr); +extern IRTEXT_CONST_PTR(kHighestStr); +extern IRTEXT_CONST_PTR(kHighStr); +extern IRTEXT_CONST_PTR(kHiStr); +extern IRTEXT_CONST_PTR(kHoldStr); +extern IRTEXT_CONST_PTR(kHoursStr); +extern IRTEXT_CONST_PTR(kHourStr); +extern IRTEXT_CONST_PTR(kHumidStr); +extern IRTEXT_CONST_PTR(kIdStr); +extern IRTEXT_CONST_PTR(kIFeelStr); +extern IRTEXT_CONST_PTR(kInsideStr); +extern IRTEXT_CONST_PTR(kIonStr); +extern IRTEXT_CONST_PTR(kJkeStr); +extern IRTEXT_CONST_PTR(kKkg29ac1Str); +extern IRTEXT_CONST_PTR(kKkg9ac1Str); +extern IRTEXT_CONST_PTR(kLastStr); +extern IRTEXT_CONST_PTR(kLeftMaxNoSpaceStr); +extern IRTEXT_CONST_PTR(kLeftMaxStr); +extern IRTEXT_CONST_PTR(kLeftStr); +extern IRTEXT_CONST_PTR(kLightStr); +extern IRTEXT_CONST_PTR(kLightToggleStr); +extern IRTEXT_CONST_PTR(kLkeStr); +extern IRTEXT_CONST_PTR(kLoStr); +extern IRTEXT_CONST_PTR(kLockStr); +extern IRTEXT_CONST_PTR(kLoudStr); +extern IRTEXT_CONST_PTR(kLowerStr); +extern IRTEXT_CONST_PTR(kLowestStr); +extern IRTEXT_CONST_PTR(kLowStr); +extern IRTEXT_CONST_PTR(kManualStr); +extern IRTEXT_CONST_PTR(kMaximumStr); +extern IRTEXT_CONST_PTR(kMaxLeftNoSpaceStr); +extern IRTEXT_CONST_PTR(kMaxLeftStr); +extern IRTEXT_CONST_PTR(kMaxRightNoSpaceStr); +extern IRTEXT_CONST_PTR(kMaxRightStr); +extern IRTEXT_CONST_PTR(kMaxStr); +extern IRTEXT_CONST_PTR(kMediumStr); +extern IRTEXT_CONST_PTR(kMedStr); +extern IRTEXT_CONST_PTR(kMiddleStr); +extern IRTEXT_CONST_PTR(kMidStr); +extern IRTEXT_CONST_PTR(kMinimumStr); +extern IRTEXT_CONST_PTR(kMinStr); +extern IRTEXT_CONST_PTR(kMinutesStr); +extern IRTEXT_CONST_PTR(kMinuteStr); +extern IRTEXT_CONST_PTR(kModelStr); +extern IRTEXT_CONST_PTR(kModeStr); +extern IRTEXT_CONST_PTR(kMouldStr); +extern IRTEXT_CONST_PTR(kMoveStr); +extern IRTEXT_CONST_PTR(kNAStr); +extern IRTEXT_CONST_PTR(kNightStr); +extern IRTEXT_CONST_PTR(kNkeStr); +extern IRTEXT_CONST_PTR(kNoStr); +extern IRTEXT_CONST_PTR(kNowStr); +extern IRTEXT_CONST_PTR(kOffStr); +extern IRTEXT_CONST_PTR(kOffTimerStr); +extern IRTEXT_CONST_PTR(kOnStr); +extern IRTEXT_CONST_PTR(kOnTimerStr); +extern IRTEXT_CONST_PTR(kOutsideQuietStr); +extern IRTEXT_CONST_PTR(kOutsideStr); +extern IRTEXT_CONST_PTR(kPanasonicCkpStr); +extern IRTEXT_CONST_PTR(kPanasonicDkeStr); +extern IRTEXT_CONST_PTR(kPanasonicJkeStr); +extern IRTEXT_CONST_PTR(kPanasonicLkeStr); +extern IRTEXT_CONST_PTR(kPanasonicNkeStr); +extern IRTEXT_CONST_PTR(kPanasonicPkrStr); +extern IRTEXT_CONST_PTR(kPanasonicRkrStr); +extern IRTEXT_CONST_PTR(kPkrStr); +extern IRTEXT_CONST_PTR(kPowerButtonStr); +extern IRTEXT_CONST_PTR(kPowerfulStr); +extern IRTEXT_CONST_PTR(kPowerStr); +extern IRTEXT_CONST_PTR(kPowerToggleStr); +extern IRTEXT_CONST_PTR(kPreviousPowerStr); +extern IRTEXT_CONST_PTR(kProtocolStr); +extern IRTEXT_CONST_PTR(kPurifyStr); +extern IRTEXT_CONST_PTR(kQuietStr); +extern IRTEXT_CONST_PTR(kRecycleStr); +extern IRTEXT_CONST_PTR(kRepeatStr); +extern IRTEXT_CONST_PTR(kRightMaxNoSpaceStr); +extern IRTEXT_CONST_PTR(kRightMaxStr); +extern IRTEXT_CONST_PTR(kRightStr); +extern IRTEXT_CONST_PTR(kRkrStr); +extern IRTEXT_CONST_PTR(kRlt0541htaaStr); +extern IRTEXT_CONST_PTR(kRlt0541htabStr); +extern IRTEXT_CONST_PTR(kRoomStr); +extern IRTEXT_CONST_PTR(kSaveStr); +extern IRTEXT_CONST_PTR(kSecondsStr); +extern IRTEXT_CONST_PTR(kSecondStr); +extern IRTEXT_CONST_PTR(kSensorStr); +extern IRTEXT_CONST_PTR(kSensorTempStr); +extern IRTEXT_CONST_PTR(kSetStr); +extern IRTEXT_CONST_PTR(kSilentStr); +extern IRTEXT_CONST_PTR(kSleepStr); +extern IRTEXT_CONST_PTR(kSleepTimerStr); +extern IRTEXT_CONST_PTR(kSlowStr); +extern IRTEXT_CONST_PTR(kSpaceLBraceStr); +extern IRTEXT_CONST_PTR(kSpecialStr); +extern IRTEXT_CONST_PTR(kStartStr); +extern IRTEXT_CONST_PTR(kStepStr); +extern IRTEXT_CONST_PTR(kStopStr); +extern IRTEXT_CONST_PTR(kSuperStr); +extern IRTEXT_CONST_PTR(kSwingHStr); +extern IRTEXT_CONST_PTR(kSwingStr); +extern IRTEXT_CONST_PTR(kSwingVModeStr); +extern IRTEXT_CONST_PTR(kSwingVStr); +extern IRTEXT_CONST_PTR(kSwingVToggleStr); +extern IRTEXT_CONST_PTR(kTac09chsdStr); +extern IRTEXT_CONST_PTR(kTempDownStr); +extern IRTEXT_CONST_PTR(kTempStr); +extern IRTEXT_CONST_PTR(kTempUpStr); +extern IRTEXT_CONST_PTR(kThreeLetterDayOfWeekStr); +extern IRTEXT_CONST_PTR(kTimerModeStr); +extern IRTEXT_CONST_PTR(kTimerStr); +extern IRTEXT_CONST_PTR(kToggleStr); +extern IRTEXT_CONST_PTR(kTopStr); +extern IRTEXT_CONST_PTR(kTrueStr); +extern IRTEXT_CONST_PTR(kTurboStr); +extern IRTEXT_CONST_PTR(kTurboToggleStr); +extern IRTEXT_CONST_PTR(kTypeStr); +extern IRTEXT_CONST_PTR(kUnknownStr); +extern IRTEXT_CONST_PTR(kUpperStr); +extern IRTEXT_CONST_PTR(kUpStr); +extern IRTEXT_CONST_PTR(kV9014557AStr); +extern IRTEXT_CONST_PTR(kV9014557BStr); +extern IRTEXT_CONST_PTR(kVaneStr); +extern IRTEXT_CONST_PTR(kWallStr); +extern IRTEXT_CONST_PTR(kWeeklyTimerStr); +extern IRTEXT_CONST_PTR(kWideStr); +extern IRTEXT_CONST_PTR(kWifiStr); +extern IRTEXT_CONST_PTR(kXFanStr); +extern IRTEXT_CONST_PTR(kYaw1fStr); +extern IRTEXT_CONST_PTR(kYbofbStr); +extern IRTEXT_CONST_PTR(kYesStr); +extern IRTEXT_CONST_PTR(kZoneFollowStr); +extern IRTEXT_CONST_PTR(kAllProtocolNamesStr); #endif // IRTEXT_H_ diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRutils.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRutils.cpp index f9892d2a4..d3a83c507 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRutils.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRutils.cpp @@ -1,4 +1,4 @@ -// Copyright 2017 David Conran +// Copyright 2017-2021 David Conran #include "IRutils.h" #ifndef UNIT_TEST @@ -17,6 +17,27 @@ #include "IRsend.h" #include "IRtext.h" +// On the ESP8266 platform we need to use a set of ..._P functions +// to handle the strings stored in the flash address space. +#ifndef STRCASECMP +#if defined(ESP8266) +#define STRCASECMP(LHS, RHS) \ + strcasecmp_P(LHS, reinterpret_cast(RHS)) +#else // ESP8266 +#define STRCASECMP strcasecmp +#endif // ESP8266 +#endif // STRCASECMP +#ifndef STRLEN +#if defined(ESP8266) +#define STRLEN(PTR) strlen_P(PTR) +#else // ESP8266 +#define STRLEN(PTR) strlen(PTR) +#endif // ESP8266 +#endif // STRLEN +#ifndef FPSTR +#define FPSTR(X) X +#endif // FPSTR + /// Reverse the order of the requested least significant nr. of bits. /// @param[in] input Bit pattern/integer to reverse. /// @param[in] nbits Nr. of bits to reverse. (LSB -> MSB) @@ -74,7 +95,10 @@ String uint64ToString(uint64_t input, uint8_t base) { /// @returns A String representation of the integer. String int64ToString(int64_t input, uint8_t base) { if (input < 0) { - return "-" + uint64ToString(-input, base); + // Using String(kDashStr) to keep compatible with old arduino + // frameworks. Not needed with 3.0.2. + ///> @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1639#issuecomment-944906016 + return String(kDashStr) + uint64ToString(-input, base); } return uint64ToString(input, base); } @@ -93,21 +117,20 @@ void serialPrintUint64(uint64_t input, uint8_t base) { /// @param[in] str A C-style string containing a protocol name or number. /// @return A decode_type_t enum. (decode_type_t::UNKNOWN if no match.) decode_type_t strToDecodeType(const char * const str) { - const char *ptr = kAllProtocolNamesStr; - uint16_t length = strlen(ptr); + auto *ptr = reinterpret_cast(kAllProtocolNamesStr); + uint16_t length = STRLEN(ptr); for (uint16_t i = 0; length; i++) { - if (!strcasecmp(str, ptr)) return (decode_type_t)i; + if (!STRCASECMP(str, ptr)) return (decode_type_t)i; ptr += length + 1; - length = strlen(ptr); + length = STRLEN(ptr); } - // Handle integer values of the type by converting to a string and back again. decode_type_t result = strToDecodeType( typeToString((decode_type_t)atoi(str)).c_str()); if (result > 0) return result; - else - return decode_type_t::UNKNOWN; + + return decode_type_t::UNKNOWN; } /// Convert a protocol type (enum etc) to a human readable string. @@ -117,16 +140,20 @@ decode_type_t strToDecodeType(const char * const str) { String typeToString(const decode_type_t protocol, const bool isRepeat) { String result = ""; result.reserve(30); // Size of longest protocol name + " (Repeat)" - const char *ptr = kAllProtocolNamesStr; if (protocol > kLastDecodeType || protocol == decode_type_t::UNKNOWN) { result = kUnknownStr; } else { - for (uint16_t i = 0; i <= protocol && strlen(ptr); i++) { - if (i == protocol) { - result = ptr; - break; + auto *ptr = reinterpret_cast(kAllProtocolNamesStr); + if (protocol > kLastDecodeType || protocol == decode_type_t::UNKNOWN) { + result = kUnknownStr; + } else { + for (uint16_t i = 0; i <= protocol && STRLEN(ptr); i++) { + if (i == protocol) { + result = FPSTR(ptr); + break; + } + ptr += STRLEN(ptr) + 1; } - ptr += strlen(ptr) + 1; } } if (isRepeat) { @@ -175,6 +202,7 @@ bool hasACState(const decode_type_t protocol) { case MWM: case NEOCLIMA: case PANASONIC_AC: + case RHOSS: case SAMSUNG_AC: case SANYO_AC: case SANYO_AC88: @@ -318,7 +346,7 @@ String resultToTimingInfo(const decode_results * const results) { for (uint16_t i = 1; i < results->rawlen; i++) { if (i % 2 == 0) - output += '-'; // even + output += kDashStr; // even else output += F(" +"); // odd value = uint64ToString(results->rawbuf[i] * kRawTick); @@ -515,7 +543,18 @@ namespace irutils { /// @return The resulting String. String addBoolToString(const bool value, const String label, const bool precomma) { - return addLabeledString((value ? kOnStr : kOffStr), label, precomma); + return addLabeledString(value ? kOnStr : kOffStr, label, precomma); + } + + /// Create a String with a colon separated toggle flag suitable for Humans. + /// e.g. "Light: Toggle", "Light: -" + /// @param[in] toggle The value of the toggle to come after the label. + /// @param[in] label The label to precede the value. + /// @param[in] precomma Should the output string start with ", " or not? + /// @return The resulting String. + String addToggleToString(const bool toggle, const String label, + const bool precomma) { + return addLabeledString(toggle ? kToggleStr : kDashStr, label, precomma); } /// Create a String with a colon separated labeled Integer suitable for @@ -547,75 +586,101 @@ namespace irutils { /// @param[in] protocol The IR protocol. /// @param[in] model The model number for that protocol. /// @return The resulting String. + /// @note After adding a new model you should update IRac::strToModel() too. String modelToStr(const decode_type_t protocol, const int16_t model) { switch (protocol) { case decode_type_t::FUJITSU_AC: switch (model) { - case fujitsu_ac_remote_model_t::ARRAH2E: return F("ARRAH2E"); - case fujitsu_ac_remote_model_t::ARDB1: return F("ARDB1"); - case fujitsu_ac_remote_model_t::ARREB1E: return F("ARREB1E"); - case fujitsu_ac_remote_model_t::ARJW2: return F("ARJW2"); - case fujitsu_ac_remote_model_t::ARRY4: return F("ARRY4"); - case fujitsu_ac_remote_model_t::ARREW4E: return F("ARREW4E"); - default: return kUnknownStr; + case fujitsu_ac_remote_model_t::ARRAH2E: return kArrah2eStr; + case fujitsu_ac_remote_model_t::ARDB1: return kArdb1Str; + case fujitsu_ac_remote_model_t::ARREB1E: return kArreb1eStr; + case fujitsu_ac_remote_model_t::ARJW2: return kArjw2Str; + case fujitsu_ac_remote_model_t::ARRY4: return kArry4Str; + case fujitsu_ac_remote_model_t::ARREW4E: return kArrew4eStr; + default: return kUnknownStr; } break; case decode_type_t::GREE: switch (model) { - case gree_ac_remote_model_t::YAW1F: return F("YAW1F"); - case gree_ac_remote_model_t::YBOFB: return F("YBOFB"); - default: return kUnknownStr; + case gree_ac_remote_model_t::YAW1F: return kYaw1fStr; + case gree_ac_remote_model_t::YBOFB: return kYbofbStr; + default: return kUnknownStr; + } + break; + case decode_type_t::HAIER_AC176: + switch (model) { + case haier_ac176_remote_model_t::V9014557_A: + return kV9014557AStr; + case haier_ac176_remote_model_t::V9014557_B: + return kV9014557BStr; + default: + return kUnknownStr; } break; case decode_type_t::HITACHI_AC1: switch (model) { case hitachi_ac1_remote_model_t::R_LT0541_HTA_A: - return F("R-LT0541-HTA-A"); + return kRlt0541htaaStr; case hitachi_ac1_remote_model_t::R_LT0541_HTA_B: - return F("R-LT0541-HTA-B"); - default: return kUnknownStr; + return kRlt0541htabStr; + default: + return kUnknownStr; } break; case decode_type_t::LG: case decode_type_t::LG2: switch (model) { - case lg_ac_remote_model_t::GE6711AR2853M: return F("GE6711AR2853M"); - case lg_ac_remote_model_t::AKB75215403: return F("AKB75215403"); - case lg_ac_remote_model_t::AKB74955603: return F("AKB74955603"); - case lg_ac_remote_model_t::AKB73757604: return F("AKB73757604"); - default: return kUnknownStr; + case lg_ac_remote_model_t::GE6711AR2853M: return kGe6711ar2853mStr; + case lg_ac_remote_model_t::AKB75215403: return kAkb75215403Str; + case lg_ac_remote_model_t::AKB74955603: return kAkb74955603Str; + case lg_ac_remote_model_t::AKB73757604: return kAkb73757604Str; + default: return kUnknownStr; } break; - case decode_type_t::SHARP_AC: + case decode_type_t::MIRAGE: switch (model) { - case sharp_ac_remote_model_t::A907: return F("A907"); - case sharp_ac_remote_model_t::A705: return F("A705"); - case sharp_ac_remote_model_t::A903: return F("A903"); - default: return kUnknownStr; + case mirage_ac_remote_model_t::KKG9AC1: return kKkg9ac1Str; + case mirage_ac_remote_model_t::KKG29AC1: return kKkg29ac1Str; + default: return kUnknownStr; } break; case decode_type_t::PANASONIC_AC: switch (model) { - case panasonic_ac_remote_model_t::kPanasonicLke: return F("LKE"); - case panasonic_ac_remote_model_t::kPanasonicNke: return F("NKE"); - case panasonic_ac_remote_model_t::kPanasonicDke: return F("DKE"); - case panasonic_ac_remote_model_t::kPanasonicJke: return F("JKE"); - case panasonic_ac_remote_model_t::kPanasonicCkp: return F("CKP"); - case panasonic_ac_remote_model_t::kPanasonicRkr: return F("RKR"); - default: return kUnknownStr; + case panasonic_ac_remote_model_t::kPanasonicLke: return kLkeStr; + case panasonic_ac_remote_model_t::kPanasonicNke: return kNkeStr; + case panasonic_ac_remote_model_t::kPanasonicDke: return kDkeStr; + case panasonic_ac_remote_model_t::kPanasonicJke: return kJkeStr; + case panasonic_ac_remote_model_t::kPanasonicCkp: return kCkpStr; + case panasonic_ac_remote_model_t::kPanasonicRkr: return kRkrStr; + default: return kUnknownStr; + } + break; + case decode_type_t::SHARP_AC: + switch (model) { + case sharp_ac_remote_model_t::A907: return kA907Str; + case sharp_ac_remote_model_t::A705: return kA705Str; + case sharp_ac_remote_model_t::A903: return kA903Str; + default: return kUnknownStr; + } + break; + case decode_type_t::TCL112AC: + switch (model) { + case tcl_ac_remote_model_t::TAC09CHSD: return kTac09chsdStr; + case tcl_ac_remote_model_t::GZ055BE1: return kGz055be1Str; + default: return kUnknownStr; } break; case decode_type_t::VOLTAS: switch (model) { - case voltas_ac_remote_model_t::kVoltas122LZF: return F("122LZF"); - default: return kUnknownStr; + case voltas_ac_remote_model_t::kVoltas122LZF: return k122lzfStr; + default: return kUnknownStr; } break; case decode_type_t::WHIRLPOOL_AC: switch (model) { - case whirlpool_ac_remote_model_t::DG11J13A: return F("DG11J13A"); - case whirlpool_ac_remote_model_t::DG11J191: return F("DG11J191"); - default: return kUnknownStr; + case whirlpool_ac_remote_model_t::DG11J13A: return kDg11j13aStr; + case whirlpool_ac_remote_model_t::DG11J191: return kDg11j191Str; + default: return kUnknownStr; } break; default: return kUnknownStr; @@ -690,8 +755,8 @@ namespace irutils { if (mode == automatic) result += kAutoStr; else if (mode == cool) result += kCoolStr; else if (mode == heat) result += kHeatStr; - else if (mode == dry) result += kDryStr; - else if (mode == fan) result += kFanStr; + else if (mode == dry) result += kDryStr; + else if (mode == fan) result += kFanStr; else result += kUnknownStr; return result + ')'; diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRutils.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRutils.h index fdda6d7ae..61fe8b269 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRutils.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/IRutils.h @@ -48,6 +48,8 @@ float fahrenheitToCelsius(const float deg); namespace irutils { String addBoolToString(const bool value, const String label, const bool precomma = true); + String addToggleToString(const bool toggle, const String label, + const bool precomma = true); String addIntToString(const uint16_t value, const String label, const bool precomma = true); String addSignedIntToString(const int16_t value, const String label, @@ -97,10 +99,10 @@ namespace irutils { bool getBit(const uint64_t data, const uint8_t position, const uint8_t size = 64); bool getBit(const uint8_t data, const uint8_t position); -#define GETBIT8(a, b) (a & ((uint8_t)1 << b)) -#define GETBIT16(a, b) (a & ((uint16_t)1 << b)) -#define GETBIT32(a, b) (a & ((uint32_t)1 << b)) -#define GETBIT64(a, b) (a & ((uint64_t)1 << b)) +#define GETBIT8(a, b) ((a) & ((uint8_t)1 << (b))) +#define GETBIT16(a, b) ((a) & ((uint16_t)1 << (b))) +#define GETBIT32(a, b) ((a) & ((uint32_t)1 << (b))) +#define GETBIT64(a, b) ((a) & ((uint64_t)1 << (b))) #define GETBITS8(data, offset, size) \ (((data) & (((uint8_t)UINT8_MAX >> (8 - (size))) << (offset))) >> (offset)) #define GETBITS16(data, offset, size) \ diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Airton.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Airton.cpp new file mode 100644 index 000000000..507894f37 --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Airton.cpp @@ -0,0 +1,70 @@ +// Copyright 2021 David Conran (crankyoldgit) +/// @file +/// @brief Support for Airton protocol +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1670 + +// Supports: +// Brand: Airton, Model: SMVH09B-2A2A3NH ref. 409730 A/C +// Brand: Airton, Model: RD1A1 remote + +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +const uint16_t kAirtonHdrMark = 6630; +const uint16_t kAirtonBitMark = 400; +const uint16_t kAirtonHdrSpace = 3350; +const uint16_t kAirtonOneSpace = 1260; +const uint16_t kAirtonZeroSpace = 430; +const uint16_t kAirtonFreq = 38000; // Hz. (Just a guess) + +#if SEND_AIRTON +// Function should be safe up to 64 bits. +/// Send a Airton formatted message. +/// Status: STABLE / Confirmed working. +/// @param[in] data containing the IR command. +/// @param[in] nbits Nr. of bits to send. usually kAirtonBits +/// @param[in] repeat Nr. of times the message is to be repeated. +void IRsend::sendAirton(const uint64_t data, const uint16_t nbits, + const uint16_t repeat) { + sendGeneric(kAirtonHdrMark, kAirtonHdrSpace, + kAirtonBitMark, kAirtonOneSpace, + kAirtonBitMark, kAirtonZeroSpace, + kAirtonBitMark, kDefaultMessageGap, + data, nbits, kAirtonFreq, false, repeat, kDutyDefault); +} +#endif // SEND_AIRTON + +#if DECODE_AIRTON +/// Decode the supplied Airton message. +/// Status: STABLE / Confirmed working. LSBF ordering confirmed via temperature. +/// @param[in,out] results Ptr to the data to decode & where to store the decode +/// @param[in] offset The starting index to use when attempting to decode the +/// raw data. Typically/Defaults to kStartOffset. +/// @param[in] nbits The number of data bits to expect. +/// @param[in] strict Flag indicating if we should perform strict matching. +/// @return A boolean. True if it can decode it, false if it can't. +bool IRrecv::decodeAirton(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen < 2 * nbits + kHeader + kFooter - offset) + return false; // Too short a message to match. + if (strict && nbits != kAirtonBits) + return false; + + // Header + Data + Footer + if (!matchGeneric(&(results->rawbuf[offset]), &(results->value), + results->rawlen - offset, nbits, + kAirtonHdrMark, kAirtonHdrSpace, + kAirtonBitMark, kAirtonOneSpace, + kAirtonBitMark, kAirtonZeroSpace, + kAirtonBitMark, kDefaultMessageGap, + true, kUseDefTol, kMarkExcess, false)) return false; + + // Success + results->decode_type = decode_type_t::AIRTON; + results->bits = nbits; + results->command = 0; + results->address = 0; + return true; +} +#endif // DECODE_AIRTON diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Arris.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Arris.cpp new file mode 100644 index 000000000..5b39808c8 --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Arris.cpp @@ -0,0 +1,123 @@ +// Copyright 2021 David Conran +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +/// @file +/// @brief Arris "Manchester code" based protocol. +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1595 + +// Supports: +// Brand: Arris, Model: VIP1113M Set-top box +// Brand: Arris, Model: 120A V1.0 A18 remote + +const uint8_t kArrisOverhead = 2; +const uint16_t kArrisHalfClockPeriod = 320; // uSeconds +const uint16_t kArrisHdrMark = 8 * kArrisHalfClockPeriod; // uSeconds +const uint16_t kArrisHdrSpace = 6 * kArrisHalfClockPeriod; // uSeconds +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1595#issuecomment-913755841 +// aka. 77184 uSeconds. +const uint32_t kArrisGapSpace = 102144 - ((8 + 6 + kArrisBits * 2) * + kArrisHalfClockPeriod); // uSeconds +const uint32_t kArrisReleaseToggle = 0x800008; +const uint8_t kArrisChecksumSize = 4; +const uint8_t kArrisCommandSize = 19; +const uint8_t kArrisReleaseBit = kArrisChecksumSize + kArrisCommandSize; + +using irutils::sumNibbles; + +#if SEND_ARRIS +/// Send an Arris Manchester Code formatted message. +/// Status: STABLE / Confirmed working. +/// @param[in] data The message to be sent. +/// @param[in] nbits The number of bits of the message to be sent. +/// @param[in] repeat The number of times the command is to be repeated. +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1595 +void IRsend::sendArris(const uint64_t data, const uint16_t nbits, + const uint16_t repeat) { + enableIROut(38); + for (uint16_t r = 0; r <= repeat; r++) { + // Header (part 1) + mark(kArrisHdrMark); + space(kArrisHdrSpace); + // Header (part 2) + Data + Footer + sendManchester(kArrisHalfClockPeriod * 2, 0, kArrisHalfClockPeriod, + 0, kArrisGapSpace, data, nbits); + } +} + +/// Flip the toggle button release bits of an Arris message. +/// Used to indicate a change of remote button's state. e.g. Press vs. Release. +/// @param[in] data The existing Arris message. +/// @return A data message suitable for use in sendArris() with the release bits +/// flipped. +uint32_t IRsend::toggleArrisRelease(const uint32_t data) { + return data ^ kArrisReleaseToggle; +} + +/// Construct a raw 32-bit Arris message code from the supplied command & +/// release setting. +/// @param[in] command The command code. +/// @param[in] release The button/command action: press (false), release (true) +/// @return A raw 32-bit Arris message code suitable for sendArris() etc. +/// @note Sequence of bits = header + release + command + checksum. +uint32_t IRsend::encodeArris(const uint32_t command, const bool release) { + uint32_t result = 0x10000000; + irutils::setBits(&result, kArrisChecksumSize, kArrisCommandSize, command); + irutils::setBit(&result, kArrisReleaseBit, release); + return result + sumNibbles(result); +} +#endif // SEND_ARRIS + +#if DECODE_ARRIS +/// Decode the supplied Arris "Manchester code" message. +/// Status: STABLE / Confirmed working. +/// @param[in,out] results Ptr to the data to decode & where to store the decode +/// result. +/// @param[in] offset The starting index to use when attempting to decode the +/// raw data. Typically/Defaults to kStartOffset. +/// @param[in] nbits The number of data bits to expect. +/// @param[in] strict Flag indicating if we should perform strict matching. +/// @return A boolean. True if it can decode it, false if it can't. +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1595 +bool IRrecv::decodeArris(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen < nbits + kArrisOverhead - offset) + return false; // Too short a message to match. + + // Compliance + if (strict && nbits != kArrisBits) + return false; // Doesn't match our protocol defn. + + // Header (part 1) + if (!matchMark(results->rawbuf[offset++], kArrisHdrMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kArrisHdrSpace)) return false; + + // Header (part 2) + Data + uint64_t data = 0; + if (!matchManchester(results->rawbuf + offset, &data, + results->rawlen - offset, nbits, + kArrisHalfClockPeriod * 2, 0, + kArrisHalfClockPeriod, 0, 0, + false, kUseDefTol, kMarkExcess, true, false)) + return false; + + // Compliance + if (strict) + // Validate the checksum. + if (GETBITS32(data, 0, kArrisChecksumSize) != + sumNibbles(data >> kArrisChecksumSize)) + return false; + + // Success + results->decode_type = decode_type_t::ARRIS; + results->bits = nbits; + results->value = data; + // Set the address as the Release Bit for something useful. + results->address = static_cast(GETBIT32(data, kArrisReleaseBit)); + // The last 4 bits are likely a checksum value, so skip those. Everything else + // after the release bit. e.g. Bits 10-28 + results->command = GETBITS32(data, kArrisChecksumSize, kArrisCommandSize); + return true; +} +#endif // DECODE_ARRIS diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Coolix.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Coolix.cpp index 1c3a40a62..f5cacf0e7 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Coolix.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Coolix.cpp @@ -611,7 +611,11 @@ String IRCoolixAC::toString(void) const { result += addBoolToString(getZoneFollow(), kZoneFollowStr); result += addLabeledString( (getSensorTemp() == kCoolixSensorTempIgnoreCode) - ? kOffStr : uint64ToString(getSensorTemp()) + 'C', kSensorTempStr); + // Encasing with String(blah) to keep compatible with old arduino + // frameworks. Not needed with 3.0.2. + ///> @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1639#issuecomment-944906016 + ? kOffStr : String(uint64ToString(getSensorTemp()) + 'C'), + kSensorTempStr); return result; } diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Electra.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Electra.cpp index fd70e4bd6..b4d670b88 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Electra.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Electra.cpp @@ -1,4 +1,4 @@ -// Copyright 2018, 2019 David Conran +// Copyright 2018-2021 David Conran /// @file /// @brief Support for Electra A/C protocols. /// @see https://github.com/ToniA/arduino-heatpumpir/blob/master/AUXHeatpumpIR.cpp @@ -28,6 +28,7 @@ using irutils::addLabeledString; using irutils::addModeToString; using irutils::addFanToString; using irutils::addTempToString; +using irutils::addToggleToString; #if SEND_ELECTRA_AC /// Send a Electra A/C formatted message. @@ -309,6 +310,52 @@ bool IRElectraAc::getTurbo(void) const { return _.Turbo; } +/// Get the IFeel mode of the A/C. +/// @return true, the setting is on. false, the setting is off. +bool IRElectraAc::getIFeel(void) const { return _.IFeel; } + +/// Set the IFeel mode of the A/C. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRElectraAc::setIFeel(const bool on) { + _.IFeel = on; + if (_.IFeel) + // Make sure there is a reasonable value in _.SensorTemp + setSensorTemp(getSensorTemp()); + else + // Clear any previous stored temp.. + _.SensorTemp = kElectraAcSensorMinTemp; +} + +/// Get the silent Sensor Update setting of the message. +/// i.e. Is this _just_ a sensor temp update message from the remote? +/// @note The A/C just takes the sensor temp value from the message and +/// will not follow any of the other settings in the message. +/// @return true, the setting is on. false, the setting is off. +bool IRElectraAc::getSensorUpdate(void) const { return _.SensorUpdate; } + +/// Set the silent Sensor Update setting of the message. +/// i.e. Is this _just_ a sensor temp update message from the remote? +/// @note The A/C will just take the sensor temp value from the message and +/// will not follow any of the other settings in the message. If set, the A/C +/// unit will also not beep in response to the message. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRElectraAc::setSensorUpdate(const bool on) { _.SensorUpdate = on; } + +/// Set the Sensor temperature for the IFeel mode. +/// @param[in] temp The temperature in degrees celsius. +void IRElectraAc::setSensorTemp(const uint8_t temp) { + _.SensorTemp = std::min(kElectraAcSensorMaxTemp, + std::max(kElectraAcSensorMinTemp, temp)) + + kElectraAcSensorTempDelta; +} + +/// Get the current sensor temperature setting for the IFeel mode. +/// @return The current setting for temp. in degrees celsius. +uint8_t IRElectraAc::getSensorTemp(void) const { + return std::max(kElectraAcSensorTempDelta, _.SensorTemp) - + kElectraAcSensorTempDelta; +} + /// Convert the current internal state into its stdAc::state_t equivalent. /// @return The stdAc equivalent of the native settings. stdAc::state_t IRElectraAc::toCommon(void) const { @@ -341,19 +388,26 @@ stdAc::state_t IRElectraAc::toCommon(void) const { /// @return A human readable string. String IRElectraAc::toString(void) const { String result = ""; - result.reserve(130); // Reserve some heap for the string to reduce fragging. - result += addBoolToString(_.Power, kPowerStr, false); - result += addModeToString(_.Mode, kElectraAcAuto, kElectraAcCool, - kElectraAcHeat, kElectraAcDry, kElectraAcFan); - result += addTempToString(getTemp()); - result += addFanToString(_.Fan, kElectraAcFanHigh, kElectraAcFanLow, - kElectraAcFanAuto, kElectraAcFanAuto, - kElectraAcFanMed); - result += addBoolToString(getSwingV(), kSwingVStr); - result += addBoolToString(getSwingH(), kSwingHStr); - result += addLabeledString(getLightToggle() ? kToggleStr : "-", kLightStr); - result += addBoolToString(_.Clean, kCleanStr); - result += addBoolToString(_.Turbo, kTurboStr); + result.reserve(160); // Reserve some heap for the string to reduce fragging. + if (!_.SensorUpdate) { + result += addBoolToString(_.Power, kPowerStr, false); + result += addModeToString(_.Mode, kElectraAcAuto, kElectraAcCool, + kElectraAcHeat, kElectraAcDry, kElectraAcFan); + result += addTempToString(getTemp()); + result += addFanToString(_.Fan, kElectraAcFanHigh, kElectraAcFanLow, + kElectraAcFanAuto, kElectraAcFanAuto, + kElectraAcFanMed); + result += addBoolToString(getSwingV(), kSwingVStr); + result += addBoolToString(getSwingH(), kSwingHStr); + result += addToggleToString(getLightToggle(), kLightStr); + result += addBoolToString(_.Clean, kCleanStr); + result += addBoolToString(_.Turbo, kTurboStr); + result += addBoolToString(_.IFeel, kIFeelStr); + } + if (_.IFeel || _.SensorUpdate) { + result += addIntToString(getSensorTemp(), kSensorTempStr, !_.SensorUpdate); + result += 'C'; + } return result; } diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Electra.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Electra.h index 886a92c56..8fd4ee182 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Electra.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Electra.h @@ -1,4 +1,4 @@ -// Copyright 2019 David Conran +// Copyright 2019-2021 David Conran /// @file /// @brief Support for Electra A/C protocols. /// @see https://github.com/ToniA/arduino-heatpumpir/blob/master/AUXHeatpumpIR.cpp @@ -9,6 +9,10 @@ // Brand: Electra, Model: Classic INV 17 / AXW12DCS A/C // Brand: Electra, Model: YKR-M/003E remote // Brand: Frigidaire, Model: FGPC102AB1 A/C +// Brand: Subtropic, Model: SUB-07HN1_18Y A/C +// Brand: Subtropic, Model: YKR-H/102E remote +// Brand: Centek, Model: SCT-65Q09 A/C +// Brand: Centek, Model: YKR-P/002E remote #ifndef IR_ELECTRA_H_ #define IR_ELECTRA_H_ @@ -37,7 +41,9 @@ union ElectraProtocol { uint8_t :5; uint8_t SwingH :3; // Byte 3 - uint8_t :8; + uint8_t :6; + uint8_t SensorUpdate :1; + uint8_t :1; // Byte 4 uint8_t :5; uint8_t Fan :3; @@ -46,10 +52,12 @@ union ElectraProtocol { uint8_t Turbo :1; uint8_t :1; // Byte 6 - uint8_t :5; + uint8_t :3; + uint8_t IFeel :1; + uint8_t :1; uint8_t Mode :3; // Byte 7 - uint8_t :8; + uint8_t SensorTemp :8; // Byte 8 uint8_t :8; // Byte 9 @@ -93,6 +101,11 @@ const uint8_t kElectraAcLightToggleMask = 0x11; // and known OFF values of 0x08 (0b00001000) & 0x05 (0x00000101) const uint8_t kElectraAcLightToggleOff = 0x08; +// Re: Byte[7]. Or Delta == 0xA and Temperature are stored in last 6 bits, +// and bit 7 stores Unknown flag +const uint8_t kElectraAcSensorTempDelta = 0x4A; +const uint8_t kElectraAcSensorMinTemp = 0; // 0C +const uint8_t kElectraAcSensorMaxTemp = 50; // 50C // Classes /// Class for handling detailed Electra A/C messages. @@ -130,6 +143,12 @@ class IRElectraAc { bool getLightToggle(void) const; void setTurbo(const bool on); bool getTurbo(void) const; + void setIFeel(const bool on); + bool getIFeel(void) const; + void setSensorUpdate(const bool on); + bool getSensorUpdate(void) const; + void setSensorTemp(const uint8_t temp); + uint8_t getSensorTemp(void) const; uint8_t* getRaw(void); void setRaw(const uint8_t new_code[], const uint16_t length = kElectraAcStateLength); diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Epson.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Epson.cpp index 4f92704bc..a92beef4f 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Epson.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Epson.cpp @@ -6,6 +6,13 @@ // Supports: // Brand: Epson, Model: EN-TW9100W Projector +// Brand: Epson, Model: VS230 Projector +// Brand: Epson, Model: VS330 Projector +// Brand: Epson, Model: EX3220 Projector +// Brand: Epson, Model: EX5220 Projector +// Brand: Epson, Model: EX5230 Projector +// Brand: Epson, Model: EX6220 Projector +// Brand: Epson, Model: EX7220 Projector #define __STDC_LIMIT_MACROS #include diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Goodweather.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Goodweather.cpp index c86797ad5..1d6918e7f 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Goodweather.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Goodweather.cpp @@ -21,6 +21,7 @@ using irutils::addLabeledString; using irutils::addModeToString; using irutils::addFanToString; using irutils::addTempToString; +using irutils::addToggleToString; #if SEND_GOODWEATHER /// Send a Goodweather HVAC formatted message. @@ -346,9 +347,10 @@ String IRGoodweatherAc::toString(void) const { result += addFanToString(_.Fan, kGoodweatherFanHigh, kGoodweatherFanLow, kGoodweatherFanAuto, kGoodweatherFanAuto, kGoodweatherFanMed); - result += addLabeledString(_.Turbo ? kToggleStr : "-", kTurboStr); - result += addLabeledString(_.Light ? kToggleStr : "-", kLightStr); - result += addLabeledString(_.Sleep ? kToggleStr : "-", kSleepStr); + + result += addToggleToString(_.Turbo, kTurboStr); + result += addToggleToString(_.Light, kLightStr); + result += addToggleToString(_.Sleep, kSleepStr); result += addIntToString(_.Swing, kSwingStr); result += kSpaceLBraceStr; switch (_.Swing) { diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Gree.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Gree.cpp index 1d1371b2d..3c3a8583e 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Gree.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Gree.cpp @@ -35,6 +35,7 @@ using irutils::addLabeledString; using irutils::addModeToString; using irutils::addModelToString; using irutils::addFanToString; +using irutils::addSwingHToString; using irutils::addTempToString; using irutils::minsToString; @@ -220,15 +221,11 @@ bool IRGreeAC::getPower(void) const { /// Set the default temperature units to use. /// @param[in] on Use Fahrenheit as the units. /// true is Fahrenheit, false is Celsius. -void IRGreeAC::setUseFahrenheit(const bool on) { - _.UseFahrenheit = on; -} +void IRGreeAC::setUseFahrenheit(const bool on) { _.UseFahrenheit = on; } /// Get the default temperature units in use. /// @return true is Fahrenheit, false is Celsius. -bool IRGreeAC::getUseFahrenheit(void) const { - return _.UseFahrenheit; -} +bool IRGreeAC::getUseFahrenheit(void) const { return _.UseFahrenheit; } /// Set the temp. in degrees /// @param[in] temp Desired temperature in Degrees. @@ -281,9 +278,7 @@ void IRGreeAC::setFan(const uint8_t speed) { /// Get the current fan speed setting. /// @return The current fan speed. -uint8_t IRGreeAC::getFan(void) const { - return _.Fan; -} +uint8_t IRGreeAC::getFan(void) const { return _.Fan; } /// Set the operating mode of the A/C. /// @param[in] new_mode The desired operating mode. @@ -305,81 +300,63 @@ void IRGreeAC::setMode(const uint8_t new_mode) { /// Get the operating mode setting of the A/C. /// @return The current operating mode setting. -uint8_t IRGreeAC::getMode(void) const { - return _.Mode; -} +uint8_t IRGreeAC::getMode(void) const { return _.Mode; } /// Set the Light (LED) setting of the A/C. /// @param[in] on true, the setting is on. false, the setting is off. -void IRGreeAC::setLight(const bool on) { - _.Light = on; -} +void IRGreeAC::setLight(const bool on) { _.Light = on; } /// Get the Light (LED) setting of the A/C. /// @return true, the setting is on. false, the setting is off. -bool IRGreeAC::getLight(void) const { - return _.Light; -} +bool IRGreeAC::getLight(void) const { return _.Light; } /// Set the IFeel setting of the A/C. /// @param[in] on true, the setting is on. false, the setting is off. -void IRGreeAC::setIFeel(const bool on) { - _.IFeel = on; -} +void IRGreeAC::setIFeel(const bool on) { _.IFeel = on; } /// Get the IFeel setting of the A/C. /// @return true, the setting is on. false, the setting is off. -bool IRGreeAC::getIFeel(void) const { - return _.IFeel; -} +bool IRGreeAC::getIFeel(void) const { return _.IFeel; } /// Set the Wifi (enabled) setting of the A/C. /// @param[in] on true, the setting is on. false, the setting is off. -void IRGreeAC::setWiFi(const bool on) { - _.WiFi = on; -} +void IRGreeAC::setWiFi(const bool on) { _.WiFi = on; } /// Get the Wifi (enabled) setting of the A/C. /// @return true, the setting is on. false, the setting is off. -bool IRGreeAC::getWiFi(void) const { - return _.WiFi; -} +bool IRGreeAC::getWiFi(void) const { return _.WiFi; } /// Set the XFan (Mould) setting of the A/C. /// @param[in] on true, the setting is on. false, the setting is off. -void IRGreeAC::setXFan(const bool on) { - _.Xfan = on; -} +void IRGreeAC::setXFan(const bool on) { _.Xfan = on; } /// Get the XFan (Mould) setting of the A/C. /// @return true, the setting is on. false, the setting is off. -bool IRGreeAC::getXFan(void) const { - return _.Xfan; -} +bool IRGreeAC::getXFan(void) const { return _.Xfan; } /// Set the Sleep setting of the A/C. /// @param[in] on true, the setting is on. false, the setting is off. -void IRGreeAC::setSleep(const bool on) { - _.Sleep = on; -} +void IRGreeAC::setSleep(const bool on) { _.Sleep = on; } /// Get the Sleep setting of the A/C. /// @return true, the setting is on. false, the setting is off. -bool IRGreeAC::getSleep(void) const { - return _.Sleep; -} +bool IRGreeAC::getSleep(void) const { return _.Sleep; } /// Set the Turbo setting of the A/C. /// @param[in] on true, the setting is on. false, the setting is off. -void IRGreeAC::setTurbo(const bool on) { - _.Turbo = on; -} +void IRGreeAC::setTurbo(const bool on) { _.Turbo = on; } /// Get the Turbo setting of the A/C. /// @return true, the setting is on. false, the setting is off. -bool IRGreeAC::getTurbo(void) const { - return _.Turbo; -} +bool IRGreeAC::getTurbo(void) const { return _.Turbo; } + +/// Set the Econo setting of the A/C. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRGreeAC::setEcono(const bool on) { _.Econo = on; } + +/// Get the Econo setting of the A/C. +/// @return true, the setting is on. false, the setting is off. +bool IRGreeAC::getEcono(void) const { return _.Econo; } /// Set the Vertical Swing mode of the A/C. /// @param[in] automatic Do we use the automatic setting? @@ -409,32 +386,37 @@ void IRGreeAC::setSwingVertical(const bool automatic, const uint8_t position) { new_position = kGreeSwingAuto; } } - _.Swing = new_position; + _.SwingV = new_position; } /// Get the Vertical Swing Automatic mode setting of the A/C. /// @return true, the setting is on. false, the setting is off. -bool IRGreeAC::getSwingVerticalAuto(void) const { - return _.SwingAuto; -} +bool IRGreeAC::getSwingVerticalAuto(void) const { return _.SwingAuto; } /// Get the Vertical Swing position setting of the A/C. /// @return The native position/mode. -uint8_t IRGreeAC::getSwingVerticalPosition(void) const { - return _.Swing; +uint8_t IRGreeAC::getSwingVerticalPosition(void) const { return _.SwingV; } + +/// Get the Horizontal Swing position setting of the A/C. +/// @return The native position/mode. +uint8_t IRGreeAC::getSwingHorizontal(void) const { return _.SwingH; } + +/// Set the Horizontal Swing mode of the A/C. +/// @param[in] position The position/mode to set the vanes to. +void IRGreeAC::setSwingHorizontal(const uint8_t position) { + if (position <= kGreeSwingHMaxRight) + _.SwingH = position; + else + _.SwingH = kGreeSwingHOff; } /// Set the timer enable setting of the A/C. /// @param[in] on true, the setting is on. false, the setting is off. -void IRGreeAC::setTimerEnabled(const bool on) { - _.TimerEnabled = on; -} +void IRGreeAC::setTimerEnabled(const bool on) { _.TimerEnabled = on; } /// Get the timer enabled setting of the A/C. /// @return true, the setting is on. false, the setting is off. -bool IRGreeAC::getTimerEnabled(void) const { - return _.TimerEnabled; -} +bool IRGreeAC::getTimerEnabled(void) const { return _.TimerEnabled; } /// Get the timer time value from the A/C. /// @return The number of minutes the timer is set for. @@ -478,9 +460,7 @@ void IRGreeAC::setDisplayTempSource(const uint8_t mode) { /// Get the temperature display mode. /// i.e. Internal, External temperature sensing. /// @return The current temp source being displayed. -uint8_t IRGreeAC::getDisplayTempSource(void) const { - return _.DisplayTemp; -} +uint8_t IRGreeAC::getDisplayTempSource(void) const { return _.DisplayTemp; } /// Convert a stdAc::opmode_t enum into its native mode. /// @param[in] mode The enum to be converted. @@ -523,6 +503,21 @@ uint8_t IRGreeAC::convertSwingV(const stdAc::swingv_t swingv) { } } +/// Convert a stdAc::swingh_t enum into it's native setting. +/// @param[in] swingh The enum to be converted. +/// @return The native equivalent of the enum. +uint8_t IRGreeAC::convertSwingH(const stdAc::swingh_t swingh) { + switch (swingh) { + case stdAc::swingh_t::kAuto: return kGreeSwingHAuto; + case stdAc::swingh_t::kLeftMax: return kGreeSwingHMaxLeft; + case stdAc::swingh_t::kLeft: return kGreeSwingHLeft; + case stdAc::swingh_t::kMiddle: return kGreeSwingHMiddle; + case stdAc::swingh_t::kRight: return kGreeSwingHRight; + case stdAc::swingh_t::kRightMax: return kGreeSwingHMaxRight; + default: return kGreeSwingHOff; + } +} + /// Convert a native mode into its stdAc equivalent. /// @param[in] mode The native setting to be converted. /// @return The stdAc equivalent of the native setting. @@ -530,9 +525,9 @@ stdAc::opmode_t IRGreeAC::toCommonMode(const uint8_t mode) { switch (mode) { case kGreeCool: return stdAc::opmode_t::kCool; case kGreeHeat: return stdAc::opmode_t::kHeat; - case kGreeDry: return stdAc::opmode_t::kDry; - case kGreeFan: return stdAc::opmode_t::kFan; - default: return stdAc::opmode_t::kAuto; + case kGreeDry: return stdAc::opmode_t::kDry; + case kGreeFan: return stdAc::opmode_t::kFan; + default: return stdAc::opmode_t::kAuto; } } @@ -541,10 +536,10 @@ stdAc::opmode_t IRGreeAC::toCommonMode(const uint8_t mode) { /// @return The stdAc equivalent of the native setting. stdAc::fanspeed_t IRGreeAC::toCommonFanSpeed(const uint8_t speed) { switch (speed) { - case kGreeFanMax: return stdAc::fanspeed_t::kMax; + case kGreeFanMax: return stdAc::fanspeed_t::kMax; case kGreeFanMax - 1: return stdAc::fanspeed_t::kMedium; - case kGreeFanMin: return stdAc::fanspeed_t::kMin; - default: return stdAc::fanspeed_t::kAuto; + case kGreeFanMin: return stdAc::fanspeed_t::kMin; + default: return stdAc::fanspeed_t::kAuto; } } @@ -553,12 +548,27 @@ stdAc::fanspeed_t IRGreeAC::toCommonFanSpeed(const uint8_t speed) { /// @return The stdAc equivalent of the native setting. stdAc::swingv_t IRGreeAC::toCommonSwingV(const uint8_t pos) { switch (pos) { - case kGreeSwingUp: return stdAc::swingv_t::kHighest; - case kGreeSwingMiddleUp: return stdAc::swingv_t::kHigh; - case kGreeSwingMiddle: return stdAc::swingv_t::kMiddle; + case kGreeSwingUp: return stdAc::swingv_t::kHighest; + case kGreeSwingMiddleUp: return stdAc::swingv_t::kHigh; + case kGreeSwingMiddle: return stdAc::swingv_t::kMiddle; case kGreeSwingMiddleDown: return stdAc::swingv_t::kLow; - case kGreeSwingDown: return stdAc::swingv_t::kLowest; - default: return stdAc::swingv_t::kAuto; + case kGreeSwingDown: return stdAc::swingv_t::kLowest; + default: return stdAc::swingv_t::kAuto; + } +} + +/// Convert a native Horizontal Swing into its stdAc equivalent. +/// @param[in] pos The native setting to be converted. +/// @return The stdAc equivalent of the native setting. +stdAc::swingh_t IRGreeAC::toCommonSwingH(const uint8_t pos) { + switch (pos) { + case kGreeSwingHAuto: return stdAc::swingh_t::kAuto; + case kGreeSwingHMaxLeft: return stdAc::swingh_t::kLeftMax; + case kGreeSwingHLeft: return stdAc::swingh_t::kLeft; + case kGreeSwingHMiddle: return stdAc::swingh_t::kMiddle; + case kGreeSwingHRight: return stdAc::swingh_t::kRight; + case kGreeSwingHMaxRight: return stdAc::swingh_t::kRightMax; + default: return stdAc::swingh_t::kOff; } } @@ -576,15 +586,15 @@ stdAc::state_t IRGreeAC::toCommon(void) { if (_.SwingAuto) result.swingv = stdAc::swingv_t::kAuto; else - result.swingv = toCommonSwingV(_.Swing); + result.swingv = toCommonSwingV(_.SwingV); + result.swingh = toCommonSwingH(_.SwingH); result.turbo = _.Turbo; + result.econo = _.Econo; result.light = _.Light; result.clean = _.Xfan; result.sleep = _.Sleep ? 0 : -1; // Not supported. - result.swingh = stdAc::swingh_t::kOff; result.quiet = false; - result.econo = false; result.filter = false; result.beep = false; result.clock = -1; @@ -604,6 +614,7 @@ String IRGreeAC::toString(void) { result += addFanToString(_.Fan, kGreeFanMax, kGreeFanMin, kGreeFanAuto, kGreeFanAuto, kGreeFanMed); result += addBoolToString(_.Turbo, kTurboStr); + result += addBoolToString(_.Econo, kEconoStr); result += addBoolToString(_.IFeel, kIFeelStr); result += addBoolToString(_.WiFi, kWifiStr); result += addBoolToString(_.Xfan, kXFanStr); @@ -611,9 +622,9 @@ String IRGreeAC::toString(void) { result += addBoolToString(_.Sleep, kSleepStr); result += addLabeledString(_.SwingAuto ? kAutoStr : kManualStr, kSwingVModeStr); - result += addIntToString(_.Swing, kSwingVStr); + result += addIntToString(_.SwingV, kSwingVStr); result += kSpaceLBraceStr; - switch (_.Swing) { + switch (_.SwingV) { case kGreeSwingLastPos: result += kLastStr; break; @@ -623,6 +634,12 @@ String IRGreeAC::toString(void) { default: result += kUnknownStr; } result += ')'; + result += addSwingHToString(_.SwingH, kGreeSwingHAuto, kGreeSwingHMaxLeft, + kGreeSwingHLeft, kGreeSwingHMiddle, + kGreeSwingHRight, kGreeSwingHMaxRight, + kGreeSwingHOff, + // rest are unused. + 0xFF, 0xFF, 0xFF, 0xFF); result += addLabeledString( _.TimerEnabled ? minsToString(getTimer()) : kOffStr, kTimerStr); uint8_t src = _.DisplayTemp; diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Gree.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Gree.h index 4f89fde5c..be5ac31ce 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Gree.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Gree.h @@ -14,10 +14,15 @@ // Brand: Green, Model: YBOFB2 remote // Brand: Gree, Model: YAA1FBF remote // Brand: Gree, Model: YB1F2F remote +// Brand: Gree, Model: YAN1F1 remote +// Brand: Gree, Model: VIR09HP115V1AH A/C +// Brand: Gree, Model: VIR12HP230V1AH A/C // Brand: Amana, Model: PBC093G00CC A/C // Brand: Amana, Model: YX1FF remote // Brand: Cooper & Hunter, Model: YB1F2 remote // Brand: Cooper & Hunter, Model: CH-S09FTXG A/C +// Brand: Vailland, Model: YACIFB remote +// Brand: Vailland, Model: VAI5-035WNI A/C #ifndef IR_GREE_H_ #define IR_GREE_H_ @@ -60,19 +65,22 @@ union GreeProtocol{ uint8_t UseFahrenheit :1; uint8_t unknown1 :4; // value=0b0101 // Byte 4 - uint8_t Swing:4; - uint8_t :0; + uint8_t SwingV :4; + uint8_t SwingH :3; + uint8_t :1; // Byte 5 uint8_t DisplayTemp :2; uint8_t IFeel :1; uint8_t unknown2 :3; // value = 0b100 uint8_t WiFi :1; - uint8_t :0; + uint8_t :1; // Byte 6 - uint8_t :8; + uint8_t :8; // Byte 7 - uint8_t :4; - uint8_t Sum:4; + uint8_t :2; + uint8_t Econo :1; + uint8_t :1; + uint8_t Sum :4; }; }; @@ -95,16 +103,24 @@ const uint8_t kGreeMinTempF = 61; // Fahrenheit const uint8_t kGreeMaxTempF = 86; // Fahrenheit const uint16_t kGreeTimerMax = 24 * 60; -const uint8_t kGreeSwingLastPos = 0b0000; -const uint8_t kGreeSwingAuto = 0b0001; -const uint8_t kGreeSwingUp = 0b0010; -const uint8_t kGreeSwingMiddleUp = 0b0011; -const uint8_t kGreeSwingMiddle = 0b0100; -const uint8_t kGreeSwingMiddleDown = 0b0101; -const uint8_t kGreeSwingDown = 0b0110; -const uint8_t kGreeSwingDownAuto = 0b0111; -const uint8_t kGreeSwingMiddleAuto = 0b1001; -const uint8_t kGreeSwingUpAuto = 0b1011; +const uint8_t kGreeSwingLastPos = 0b0000; // 0 +const uint8_t kGreeSwingAuto = 0b0001; // 1 +const uint8_t kGreeSwingUp = 0b0010; // 2 +const uint8_t kGreeSwingMiddleUp = 0b0011; // 3 +const uint8_t kGreeSwingMiddle = 0b0100; // 4 +const uint8_t kGreeSwingMiddleDown = 0b0101; // 5 +const uint8_t kGreeSwingDown = 0b0110; // 6 +const uint8_t kGreeSwingDownAuto = 0b0111; // 7 +const uint8_t kGreeSwingMiddleAuto = 0b1001; // 9 +const uint8_t kGreeSwingUpAuto = 0b1011; // 11 + +const uint8_t kGreeSwingHOff = 0b000; // 0 +const uint8_t kGreeSwingHAuto = 0b001; // 1 +const uint8_t kGreeSwingHMaxLeft = 0b010; // 2 +const uint8_t kGreeSwingHLeft = 0b011; // 3 +const uint8_t kGreeSwingHMiddle = 0b100; // 4 +const uint8_t kGreeSwingHRight = 0b101; // 5 +const uint8_t kGreeSwingHMaxRight = 0b110; // 6 const uint8_t kGreeDisplayTempOff = 0b00; // 0 const uint8_t kGreeDisplayTempSet = 0b01; // 1 @@ -171,6 +187,8 @@ class IRGreeAC { bool getSleep(void) const; void setTurbo(const bool on); bool getTurbo(void) const; + void setEcono(const bool on); + bool getEcono(void) const; void setIFeel(const bool on); bool getIFeel(void) const; void setWiFi(const bool on); @@ -178,6 +196,8 @@ class IRGreeAC { void setSwingVertical(const bool automatic, const uint8_t position); bool getSwingVerticalAuto(void) const; uint8_t getSwingVerticalPosition(void) const; + void setSwingHorizontal(const uint8_t position); + uint8_t getSwingHorizontal(void) const; uint16_t getTimer(void) const; void setTimer(const uint16_t minutes); void setDisplayTempSource(const uint8_t mode); @@ -185,9 +205,11 @@ class IRGreeAC { static uint8_t convertMode(const stdAc::opmode_t mode); static uint8_t convertFan(const stdAc::fanspeed_t speed); static uint8_t convertSwingV(const stdAc::swingv_t swingv); + static uint8_t convertSwingH(const stdAc::swingh_t swingh); static stdAc::opmode_t toCommonMode(const uint8_t mode); static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed); static stdAc::swingv_t toCommonSwingV(const uint8_t pos); + static stdAc::swingh_t toCommonSwingH(const uint8_t pos); stdAc::state_t toCommon(void); uint8_t* getRaw(void); void setRaw(const uint8_t new_code[]); diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Haier.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Haier.cpp index a43e9400d..5c9f2a36d 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Haier.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Haier.cpp @@ -32,6 +32,8 @@ using irutils::addBoolToString; using irutils::addIntToString; using irutils::addLabeledString; using irutils::addModeToString; +using irutils::addModelToString; +using irutils::addSwingHToString; using irutils::addFanToString; using irutils::addTempToString; using irutils::minsToString; @@ -322,22 +324,22 @@ void IRHaierAC::setCurrTime(const uint16_t nr_mins) { } /// Get the Vertical Swing position setting of the A/C. -/// @return The native swing mode. -uint8_t IRHaierAC::getSwing(void) const { - return _.Swing; +/// @return The native vertical swing mode. +uint8_t IRHaierAC::getSwingV(void) const { + return _.SwingV; } /// Set the Vertical Swing mode of the A/C. /// @param[in] state The mode to set the vanes to. -void IRHaierAC::setSwing(const uint8_t state) { - if (state == _.Swing) return; // Nothing to do. +void IRHaierAC::setSwingV(const uint8_t state) { + if (state == _.SwingV) return; // Nothing to do. switch (state) { - case kHaierAcSwingOff: - case kHaierAcSwingUp: - case kHaierAcSwingDown: - case kHaierAcSwingChg: + case kHaierAcSwingVOff: + case kHaierAcSwingVUp: + case kHaierAcSwingVDown: + case kHaierAcSwingVChg: _.Command = kHaierAcCmdSwing; - _.Swing = state; + _.SwingV = state; break; } } @@ -376,11 +378,11 @@ uint8_t IRHaierAC::convertSwingV(const stdAc::swingv_t position) { switch (position) { case stdAc::swingv_t::kHighest: case stdAc::swingv_t::kHigh: - case stdAc::swingv_t::kMiddle: return kHaierAcSwingUp; + case stdAc::swingv_t::kMiddle: return kHaierAcSwingVUp; case stdAc::swingv_t::kLow: - case stdAc::swingv_t::kLowest: return kHaierAcSwingDown; - case stdAc::swingv_t::kOff: return kHaierAcSwingOff; - default: return kHaierAcSwingChg; + case stdAc::swingv_t::kLowest: return kHaierAcSwingVDown; + case stdAc::swingv_t::kOff: return kHaierAcSwingVOff; + default: return kHaierAcSwingVChg; } } @@ -414,10 +416,10 @@ stdAc::fanspeed_t IRHaierAC::toCommonFanSpeed(const uint8_t speed) { /// @return The native equivalent of the enum. stdAc::swingv_t IRHaierAC::toCommonSwingV(const uint8_t pos) { switch (pos) { - case kHaierAcSwingUp: return stdAc::swingv_t::kHighest; - case kHaierAcSwingDown: return stdAc::swingv_t::kLowest; - case kHaierAcSwingOff: return stdAc::swingv_t::kOff; - default: return stdAc::swingv_t::kAuto; + case kHaierAcSwingVUp: return stdAc::swingv_t::kHighest; + case kHaierAcSwingVDown: return stdAc::swingv_t::kLowest; + case kHaierAcSwingVOff: return stdAc::swingv_t::kOff; + default: return stdAc::swingv_t::kAuto; } } @@ -433,7 +435,7 @@ stdAc::state_t IRHaierAC::toCommon(void) const { result.celsius = true; result.degrees = getTemp(); result.fanspeed = toCommonFanSpeed(getFan()); - result.swingv = toCommonSwingV(_.Swing); + result.swingv = toCommonSwingV(_.SwingV); result.filter = _.Health; result.sleep = _.Sleep ? 0 : -1; // Not supported. @@ -443,7 +445,7 @@ stdAc::state_t IRHaierAC::toCommon(void) const { result.econo = false; result.light = false; result.clean = false; - result.beep = false; + result.beep = true; result.clock = -1; return result; } @@ -452,7 +454,7 @@ stdAc::state_t IRHaierAC::toCommon(void) const { /// @return A human readable string. String IRHaierAC::toString(void) const { String result = ""; - result.reserve(150); // Reserve some heap for the string to reduce fragging. + result.reserve(170); // Reserve some heap for the string to reduce fragging. uint8_t cmd = _.Command; result += addIntToString(cmd, kCommandStr, false); result += kSpaceLBraceStr; @@ -492,7 +494,7 @@ String IRHaierAC::toString(void) const { result += kHealthStr; break; case kHaierAcCmdSwing: - result += kSwingStr; + result += kSwingVStr; break; default: result += kUnknownStr; @@ -503,19 +505,19 @@ String IRHaierAC::toString(void) const { result += addTempToString(getTemp()); result += addFanToString(getFan(), kHaierAcFanHigh, kHaierAcFanLow, kHaierAcFanAuto, kHaierAcFanAuto, kHaierAcFanMed); - result += addIntToString(_.Swing, kSwingStr); + result += addIntToString(_.SwingV, kSwingVStr); result += kSpaceLBraceStr; - switch (_.Swing) { - case kHaierAcSwingOff: + switch (_.SwingV) { + case kHaierAcSwingVOff: result += kOffStr; break; - case kHaierAcSwingUp: + case kHaierAcSwingVUp: result += kUpStr; break; - case kHaierAcSwingDown: + case kHaierAcSwingVDown: result += kDownStr; break; - case kHaierAcSwingChg: + case kHaierAcSwingVChg: result += kChangeStr; break; default: @@ -581,9 +583,9 @@ bool IRHaierAC176::validChecksum(const uint8_t state[], const uint16_t length) { /// Reset the internal state to a fixed known good state. void IRHaierAC176::stateReset(void) { std::memset(_.raw, 0, sizeof _.raw); - _.Prefix = kHaierAcYrw02Prefix; + _.Model = kHaierAcYrw02ModelA; _.Prefix2 = kHaierAc176Prefix; - _.Temp = kHaierAcDefTemp - kHaierAcMinTemp; + _.Temp = kHaierAcYrw02DefTempC - kHaierAcYrw02MinTempC; _.Health = true; setFan(kHaierAcYrw02FanAuto); _.Power = true; @@ -609,17 +611,42 @@ void IRHaierAC176::setButton(uint8_t button) { switch (button) { case kHaierAcYrw02ButtonTempUp: case kHaierAcYrw02ButtonTempDown: - case kHaierAcYrw02ButtonSwing: + case kHaierAcYrw02ButtonSwingV: + case kHaierAcYrw02ButtonSwingH: case kHaierAcYrw02ButtonFan: case kHaierAcYrw02ButtonPower: case kHaierAcYrw02ButtonMode: case kHaierAcYrw02ButtonHealth: case kHaierAcYrw02ButtonTurbo: case kHaierAcYrw02ButtonSleep: + case kHaierAcYrw02ButtonLock: + case kHaierAcYrw02ButtonCFAB: _.Button = button; } } +/// Get/Detect the model of the A/C. +/// @return The enum of the compatible model. +haier_ac176_remote_model_t IRHaierAC176::getModel(void) const { + switch (_.Model) { + case kHaierAcYrw02ModelB: return haier_ac176_remote_model_t::V9014557_B; + default: return haier_ac176_remote_model_t::V9014557_A; + } +} + +/// Set the model of the A/C to emulate. +/// @param[in] model The enum of the appropriate model. +void IRHaierAC176::setModel(haier_ac176_remote_model_t model) { + _.Button = kHaierAcYrw02ButtonCFAB; + switch (model) { + case haier_ac176_remote_model_t::V9014557_B: + _.Model = kHaierAcYrw02ModelB; + break; + default: + _.Model = kHaierAcYrw02ModelA; + } +} + /// Get the Button/Command setting of the A/C. /// @return The value of the button/command that was pressed. uint8_t IRHaierAC176::getButton(void) const { @@ -629,47 +656,118 @@ uint8_t IRHaierAC176::getButton(void) const { /// Set the operating mode of the A/C. /// @param[in] mode The desired operating mode. void IRHaierAC176::setMode(uint8_t mode) { - uint8_t new_mode = mode; - _.Button = kHaierAcYrw02ButtonMode; switch (mode) { case kHaierAcYrw02Auto: - case kHaierAcYrw02Cool: case kHaierAcYrw02Dry: + case kHaierAcYrw02Fan: + // Turbo & Quiet is only available in Cool/Heat mode. + _.Turbo = false; + _.Quiet = false; + // FALL-THRU + case kHaierAcYrw02Cool: case kHaierAcYrw02Heat: - case kHaierAcYrw02Fan: break; - default: new_mode = kHaierAcYrw02Auto; // Unexpected, default to auto mode. + _.Button = kHaierAcYrw02ButtonMode; + _.Mode = mode; + break; + default: + setMode(kHaierAcYrw02Auto); // Unexpected, default to auto mode. } - _.Mode = new_mode; } /// Get the operating mode setting of the A/C. /// @return The current operating mode setting. -uint8_t IRHaierAC176::getMode(void) const { - return _.Mode; -} +uint8_t IRHaierAC176::getMode(void) const { return _.Mode; } + +/// Set the default temperature units to use. +/// @param[in] on Use Fahrenheit as the units. +/// true is Fahrenheit, false is Celsius. +void IRHaierAC176::setUseFahrenheit(const bool on) { _.UseFahrenheit = on; } + +/// Get the default temperature units in use. +/// @return true is Fahrenheit, false is Celsius. +bool IRHaierAC176::getUseFahrenheit(void) const { return _.UseFahrenheit; } /// Set the temperature. -/// @param[in] celsius The temperature in degrees celsius. -void IRHaierAC176::setTemp(const uint8_t celsius) { - uint8_t temp = celsius; - if (temp < kHaierAcMinTemp) - temp = kHaierAcMinTemp; - else if (temp > kHaierAcMaxTemp) - temp = kHaierAcMaxTemp; - +/// @param[in] degree The temperature in degrees. +/// @param[in] fahrenheit Use units of Fahrenheit and set that as units used. +void IRHaierAC176::setTemp(const uint8_t degree, const bool fahrenheit) { uint8_t old_temp = getTemp(); - if (old_temp == temp) return; - if (old_temp > temp) - _.Button = kHaierAcYrw02ButtonTempDown; - else - _.Button = kHaierAcYrw02ButtonTempUp; - _.Temp = temp - kHaierAcMinTemp; + if (old_temp == degree) return; + + if (_.UseFahrenheit == fahrenheit) { + if (old_temp > degree) + _.Button = kHaierAcYrw02ButtonTempDown; + else + _.Button = kHaierAcYrw02ButtonTempUp; + } else { + _.Button = kHaierAcYrw02ButtonCFAB; + } + _.UseFahrenheit = fahrenheit; + + uint8_t temp = degree; + if (fahrenheit) { + if (temp < kHaierAcYrw02MinTempF) + temp = kHaierAcYrw02MinTempF; + else if (temp > kHaierAcYrw02MaxTempF) + temp = kHaierAcYrw02MaxTempF; + if (degree >= 77) { temp++; } + if (degree >= 79) { temp++; } + // See at IRHaierAC176::getTemp() comments for clarification + _.ExtraDegreeF = temp % 2; + _.Temp = (temp - kHaierAcYrw02MinTempF -_.ExtraDegreeF) >> 1; + } else { + if (temp < kHaierAcYrw02MinTempC) + temp = kHaierAcYrw02MinTempC; + else if (temp > kHaierAcYrw02MaxTempC) + temp = kHaierAcYrw02MaxTempC; + _.Temp = temp - kHaierAcYrw02MinTempC; + } } /// Get the current temperature setting. -/// @return The current setting for temp. in degrees celsius. +/// The unit of temperature is specified by UseFahrenheit value. +/// @return The current setting for temperature. uint8_t IRHaierAC176::getTemp(void) const { - return _.Temp + kHaierAcMinTemp; + if (!_.UseFahrenheit) { return _.Temp + kHaierAcYrw02MinTempC; } + uint8_t degree = _.Temp*2 + kHaierAcYrw02MinTempF + _.ExtraDegreeF; + // The way of coding the temperature in degree Fahrenheit is + // kHaierAcYrw02MinTempF + Temp*2 + ExtraDegreeF, for example + // Temp = 0b0011, ExtraDegreeF = 0b1, temperature is 60 + 3*2 + 1 = 67F + // But around 78F there is unconsistency, see table below + // + // | Fahrenheit | Temp | ExtraDegreeF | + // | 60F | 0b0000 | 0b0 | + // | 61F | 0b0000 | 0b1 | + // | 62F | 0b0001 | 0b0 | + // | 63F | 0b0001 | 0b1 | + // | 64F | 0b0010 | 0b0 | + // | 65F | 0b0010 | 0b1 | + // | 66F | 0b0011 | 0b0 | + // | 67F | 0b0011 | 0b1 | + // | 68F | 0b0100 | 0b0 | + // | 69F | 0b0100 | 0b1 | + // | 70F | 0b0101 | 0b0 | + // | 71F | 0b0101 | 0b1 | + // | 72F | 0b0110 | 0b0 | + // | 73F | 0b0110 | 0b1 | + // | 74F | 0b0111 | 0b0 | + // | 75F | 0b0111 | 0b1 | + // | 76F | 0b1000 | 0b0 | + // | Not Used | 0b1000 | 0b1 | + // | 77F | 0b1001 | 0b0 | + // | Not Used | 0b1001 | 0b1 | + // | 78F | 0b1010 | 0b0 | + // | 79F | 0b1010 | 0b1 | + // | 80F | 0b1011 | 0b0 | + // | 81F | 0b1011 | 0b1 | + // | 82F | 0b1100 | 0b0 | + // | 83F | 0b1100 | 0b1 | + // | 84F | 0b1101 | 0b0 | + // | 86F | 0b1110 | 0b0 | + // | 85F | 0b1101 | 0b1 | + if (degree >= 77) { degree--; } + if (degree >= 79) { degree--; } + return degree; } /// Set the Health (filter) setting of the A/C. @@ -681,15 +779,11 @@ void IRHaierAC176::setHealth(const bool on) { /// Get the Health (filter) setting of the A/C. /// @return true, the setting is on. false, the setting is off. -bool IRHaierAC176::getHealth(void) const { - return _.Health; -} +bool IRHaierAC176::getHealth(void) const { return _.Health; } /// Get the value of the current power setting. /// @return true, the setting is on. false, the setting is off. -bool IRHaierAC176::getPower(void) const { - return _.Power; -} +bool IRHaierAC176::getPower(void) const { return _.Power; } /// Change the power setting. /// @param[in] on true, the setting is on. false, the setting is off. @@ -706,9 +800,7 @@ void IRHaierAC176::off(void) { setPower(false); } /// Get the Sleep setting of the A/C. /// @return true, the setting is on. false, the setting is off. -bool IRHaierAC176::getSleep(void) const { - return _.Sleep; -} +bool IRHaierAC176::getSleep(void) const { return _.Sleep; } /// Set the Sleep setting of the A/C. /// @param[in] on true, the setting is on. false, the setting is off. @@ -718,30 +810,42 @@ void IRHaierAC176::setSleep(const bool on) { } /// Get the Turbo setting of the A/C. -/// @return The current turbo speed setting. -uint8_t IRHaierAC176::getTurbo(void) const { - return _.Turbo; -} +/// @return The current turbo setting. +bool IRHaierAC176::getTurbo(void) const { return _.Turbo; } /// Set the Turbo setting of the A/C. -/// @param[in] speed The desired turbo speed setting. -/// @note Valid speeds are kHaierAcYrw02TurboOff, kHaierAcYrw02TurboLow, & -/// kHaierAcYrw02TurboHigh. -void IRHaierAC176::setTurbo(uint8_t speed) { - switch (speed) { - case kHaierAcYrw02TurboOff: - case kHaierAcYrw02TurboLow: - case kHaierAcYrw02TurboHigh: - _.Turbo = speed; +/// @param[in] on The desired turbo setting. +/// @note Turbo & Quiet can't be on at the same time, and only in Heat/Cool mode +void IRHaierAC176::setTurbo(const bool on) { + switch (getMode()) { + case kHaierAcYrw02Cool: + case kHaierAcYrw02Heat: + _.Turbo = on; _.Button = kHaierAcYrw02ButtonTurbo; + if (on) _.Quiet = false; + } +} + +/// Get the Quiet setting of the A/C. +/// @return The current Quiet setting. +bool IRHaierAC176::getQuiet(void) const { return _.Quiet; } + +/// Set the Quiet setting of the A/C. +/// @param[in] on The desired Quiet setting. +/// @note Turbo & Quiet can't be on at the same time, and only in Heat/Cool mode +void IRHaierAC176::setQuiet(const bool on) { + switch (getMode()) { + case kHaierAcYrw02Cool: + case kHaierAcYrw02Heat: + _.Quiet = on; + _.Button = kHaierAcYrw02ButtonTurbo; + if (on) _.Turbo = false; } } /// Get the current fan speed setting. /// @return The current fan speed. -uint8_t IRHaierAC176::getFan(void) const { - return _.Fan; -} +uint8_t IRHaierAC176::getFan(void) const { return _.Fan; } /// Set the speed of the fan. /// @param[in] speed The desired setting. @@ -757,30 +861,61 @@ void IRHaierAC176::setFan(uint8_t speed) { } } +/// For backward compatibility. Use getSwingV() instead. /// Get the Vertical Swing position setting of the A/C. /// @return The native position/mode. -uint8_t IRHaierAC176::getSwing(void) const { return _.Swing; } +uint8_t IRHaierAC176::getSwing(void) const { + return IRHaierAC176::getSwingV(); +} + +/// For backward compatibility. Use setSwingV() instead. +/// Set the Vertical Swing mode of the A/C. +/// @param[in] pos The position/mode to set the vanes to. +void IRHaierAC176::setSwing(uint8_t pos) { setSwingV(pos); } + +/// Get the Vertical Swing position setting of the A/C. +/// @return The native position/mode. +uint8_t IRHaierAC176::getSwingV(void) const { return _.SwingV; } /// Set the Vertical Swing mode of the A/C. /// @param[in] pos The position/mode to set the vanes to. -void IRHaierAC176::setSwing(uint8_t pos) { +void IRHaierAC176::setSwingV(uint8_t pos) { uint8_t newpos = pos; switch (pos) { - case kHaierAcYrw02SwingOff: - case kHaierAcYrw02SwingAuto: - case kHaierAcYrw02SwingTop: - case kHaierAcYrw02SwingMiddle: - case kHaierAcYrw02SwingBottom: - case kHaierAcYrw02SwingDown: _.Button = kHaierAcYrw02ButtonSwing; break; + case kHaierAcYrw02SwingVOff: + case kHaierAcYrw02SwingVAuto: + case kHaierAcYrw02SwingVTop: + case kHaierAcYrw02SwingVMiddle: + case kHaierAcYrw02SwingVBottom: + case kHaierAcYrw02SwingVDown: _.Button = kHaierAcYrw02ButtonSwingV; break; default: return; // Unexpected value so don't do anything. } // Heat mode has no MIDDLE setting, use BOTTOM instead. - if (pos == kHaierAcYrw02SwingMiddle && _.Mode == kHaierAcYrw02Heat) - newpos = kHaierAcYrw02SwingBottom; + if (pos == kHaierAcYrw02SwingVMiddle && _.Mode == kHaierAcYrw02Heat) + newpos = kHaierAcYrw02SwingVBottom; // BOTTOM is only allowed if we are in Heat mode, otherwise MIDDLE. - if (pos == kHaierAcYrw02SwingBottom && _.Mode != kHaierAcYrw02Heat) - newpos = kHaierAcYrw02SwingMiddle; - _.Swing = newpos; + if (pos == kHaierAcYrw02SwingVBottom && _.Mode != kHaierAcYrw02Heat) + newpos = kHaierAcYrw02SwingVMiddle; + _.SwingV = newpos; +} + +/// Get the Horizontal Swing position setting of the A/C. +/// @return The native position/mode. +uint8_t IRHaierAC176::getSwingH(void) const { return _.SwingH; } + +/// Set the Horizontal Swing mode of the A/C. +/// @param[in] pos The position/mode to set the vanes to. +void IRHaierAC176::setSwingH(uint8_t pos) { + switch (pos) { + case kHaierAcYrw02SwingHMiddle: + case kHaierAcYrw02SwingHLeftMax: + case kHaierAcYrw02SwingHLeft: + case kHaierAcYrw02SwingHRight: + case kHaierAcYrw02SwingHRightMax: + case kHaierAcYrw02SwingHAuto: _.Button = kHaierAcYrw02ButtonSwingH; break; + default: return; // Unexpected value so don't do anything. + } + _.SwingH = pos; } @@ -867,6 +1002,17 @@ uint16_t IRHaierAC176::getOffTimer(void) const { return _.OffTimerHrs * 60 + _.OffTimerMins; } +/// Get the Lock setting of the A/C. +/// @return true, the setting is on. false, the setting is off. +bool IRHaierAC176::getLock(void) const { return _.Lock; } + +/// Set the Lock setting of the A/C. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRHaierAC176::setLock(const bool on) { + _.Button = kHaierAcYrw02ButtonLock; + _.Lock = on; +} + /// Convert a stdAc::opmode_t enum into its native mode. /// @param[in] mode The enum to be converted. /// @return The native equivalent of the enum. @@ -900,12 +1046,27 @@ uint8_t IRHaierAC176::convertFan(const stdAc::fanspeed_t speed) { uint8_t IRHaierAC176::convertSwingV(const stdAc::swingv_t position) { switch (position) { case stdAc::swingv_t::kHighest: - case stdAc::swingv_t::kHigh: return kHaierAcYrw02SwingTop; - case stdAc::swingv_t::kMiddle: return kHaierAcYrw02SwingMiddle; - case stdAc::swingv_t::kLow: return kHaierAcYrw02SwingDown; - case stdAc::swingv_t::kLowest: return kHaierAcYrw02SwingBottom; - case stdAc::swingv_t::kOff: return kHaierAcYrw02SwingOff; - default: return kHaierAcYrw02SwingAuto; + case stdAc::swingv_t::kHigh: return kHaierAcYrw02SwingVTop; + case stdAc::swingv_t::kMiddle: return kHaierAcYrw02SwingVMiddle; + case stdAc::swingv_t::kLow: return kHaierAcYrw02SwingVDown; + case stdAc::swingv_t::kLowest: return kHaierAcYrw02SwingVBottom; + case stdAc::swingv_t::kOff: return kHaierAcYrw02SwingVOff; + default: return kHaierAcYrw02SwingVAuto; + } +} + +/// Convert a stdAc::swingh_t enum into it's native setting. +/// @param[in] position The enum to be converted. +/// @return The native equivalent of the enum. +uint8_t IRHaierAC176::convertSwingH(const stdAc::swingh_t position) { + switch (position) { + case stdAc::swingh_t::kMiddle: return kHaierAcYrw02SwingHMiddle; + case stdAc::swingh_t::kLeftMax: return kHaierAcYrw02SwingHLeftMax; + case stdAc::swingh_t::kLeft: return kHaierAcYrw02SwingHLeft; + case stdAc::swingh_t::kRight: return kHaierAcYrw02SwingHRight; + case stdAc::swingh_t::kRightMax: return kHaierAcYrw02SwingHRightMax; + case stdAc::swingh_t::kAuto: return kHaierAcYrw02SwingHAuto; + default: return kHaierAcYrw02SwingHMiddle; } } @@ -939,12 +1100,27 @@ stdAc::fanspeed_t IRHaierAC176::toCommonFanSpeed(const uint8_t speed) { /// @return The native equivalent of the enum. stdAc::swingv_t IRHaierAC176::toCommonSwingV(const uint8_t pos) { switch (pos) { - case kHaierAcYrw02SwingTop: return stdAc::swingv_t::kHighest; - case kHaierAcYrw02SwingMiddle: return stdAc::swingv_t::kMiddle; - case kHaierAcYrw02SwingDown: return stdAc::swingv_t::kLow; - case kHaierAcYrw02SwingBottom: return stdAc::swingv_t::kLowest; - case kHaierAcYrw02SwingOff: return stdAc::swingv_t::kOff; - default: return stdAc::swingv_t::kAuto; + case kHaierAcYrw02SwingVTop: return stdAc::swingv_t::kHighest; + case kHaierAcYrw02SwingVMiddle: return stdAc::swingv_t::kMiddle; + case kHaierAcYrw02SwingVDown: return stdAc::swingv_t::kLow; + case kHaierAcYrw02SwingVBottom: return stdAc::swingv_t::kLowest; + case kHaierAcYrw02SwingVOff: return stdAc::swingv_t::kOff; + default: return stdAc::swingv_t::kAuto; + } +} + +/// Convert a stdAc::swingh_t enum into it's native setting. +/// @param[in] pos The enum to be converted. +/// @return The native equivalent of the enum. +stdAc::swingh_t IRHaierAC176::toCommonSwingH(const uint8_t pos) { + switch (pos) { + case kHaierAcYrw02SwingHMiddle: return stdAc::swingh_t::kMiddle; + case kHaierAcYrw02SwingHLeftMax: return stdAc::swingh_t::kLeftMax; + case kHaierAcYrw02SwingHLeft: return stdAc::swingh_t::kLeft; + case kHaierAcYrw02SwingHRight: return stdAc::swingh_t::kRight; + case kHaierAcYrw02SwingHRightMax: return stdAc::swingh_t::kRightMax; + case kHaierAcYrw02SwingHAuto: return stdAc::swingh_t::kAuto; + default: return stdAc::swingh_t::kOff; } } @@ -953,23 +1129,23 @@ stdAc::swingv_t IRHaierAC176::toCommonSwingV(const uint8_t pos) { stdAc::state_t IRHaierAC176::toCommon(void) const { stdAc::state_t result; result.protocol = decode_type_t::HAIER_AC_YRW02; - result.model = -1; // No models used. + result.model = getModel(); result.power = _.Power; result.mode = toCommonMode(_.Mode); - result.celsius = true; + result.celsius = !_.UseFahrenheit; result.degrees = getTemp(); result.fanspeed = toCommonFanSpeed(_.Fan); - result.swingv = toCommonSwingV(_.Swing); + result.swingv = toCommonSwingV(_.SwingV); + result.swingh = toCommonSwingH(_.SwingH); result.filter = _.Health; result.sleep = _.Sleep ? 0 : -1; + result.turbo = _.Turbo; + result.quiet = _.Quiet; // Not supported. - result.swingh = stdAc::swingh_t::kOff; - result.quiet = false; - result.turbo = false; result.econo = false; result.light = false; result.clean = false; - result.beep = false; + result.beep = true; result.clock = -1; return result; } @@ -978,8 +1154,9 @@ stdAc::state_t IRHaierAC176::toCommon(void) const { /// @return A human readable string. String IRHaierAC176::toString(void) const { String result = ""; - result.reserve(130); // Reserve some heap for the string to reduce fragging. - result += addBoolToString(_.Power, kPowerStr, false); + result.reserve(280); // Reserve some heap for the string to reduce fragging. + result += addModelToString(decode_type_t::HAIER_AC176, getModel(), false); + result += addBoolToString(_.Power, kPowerStr); uint8_t cmd = _.Button; result += addIntToString(cmd, kButtonStr); result += kSpaceLBraceStr; @@ -1005,12 +1182,24 @@ String IRHaierAC176::toString(void) const { case kHaierAcYrw02ButtonHealth: result += kHealthStr; break; - case kHaierAcYrw02ButtonSwing: - result += kSwingStr; + case kHaierAcYrw02ButtonSwingV: + result += kSwingVStr; + break; + case kHaierAcYrw02ButtonSwingH: + result += kSwingHStr; break; case kHaierAcYrw02ButtonTurbo: result += kTurboStr; break; + case kHaierAcYrw02ButtonTimer: + result += kTimerStr; + break; + case kHaierAcYrw02ButtonLock: + result += kLockStr; + break; + case kHaierAcYrw02ButtonCFAB: + result += kCelsiusFahrenheitStr; + break; default: result += kUnknownStr; } @@ -1018,51 +1207,49 @@ String IRHaierAC176::toString(void) const { result += addModeToString(_.Mode, kHaierAcYrw02Auto, kHaierAcYrw02Cool, kHaierAcYrw02Heat, kHaierAcYrw02Dry, kHaierAcYrw02Fan); - result += addTempToString(getTemp()); + result += addTempToString(getTemp(), !_.UseFahrenheit); result += addFanToString(_.Fan, kHaierAcYrw02FanHigh, kHaierAcYrw02FanLow, kHaierAcYrw02FanAuto, kHaierAcYrw02FanAuto, kHaierAcYrw02FanMed); - result += addIntToString(_.Turbo, kTurboStr); + result += addBoolToString(_.Turbo, kTurboStr); + result += addBoolToString(_.Quiet, kQuietStr); + result += addIntToString(_.SwingV, kSwingVStr); result += kSpaceLBraceStr; - switch (_.Turbo) { - case kHaierAcYrw02TurboOff: + switch (_.SwingV) { + case kHaierAcYrw02SwingVOff: result += kOffStr; break; - case kHaierAcYrw02TurboLow: - result += kLowStr; - break; - case kHaierAcYrw02TurboHigh: - result += kHighStr; - break; - default: - result += kUnknownStr; - } - result += ')'; - result += addIntToString(_.Swing, kSwingStr); - result += kSpaceLBraceStr; - switch (_.Swing) { - case kHaierAcYrw02SwingOff: - result += kOffStr; - break; - case kHaierAcYrw02SwingAuto: + case kHaierAcYrw02SwingVAuto: result += kAutoStr; break; - case kHaierAcYrw02SwingBottom: + case kHaierAcYrw02SwingVBottom: result += kLowestStr; break; - case kHaierAcYrw02SwingDown: + case kHaierAcYrw02SwingVDown: result += kLowStr; break; - case kHaierAcYrw02SwingTop: + case kHaierAcYrw02SwingVTop: result += kHighestStr; break; - case kHaierAcYrw02SwingMiddle: + case kHaierAcYrw02SwingVMiddle: result += kMiddleStr; break; default: result += kUnknownStr; } result += ')'; + result += addSwingHToString(_.SwingH, kHaierAcYrw02SwingHAuto, + kHaierAcYrw02SwingHLeftMax, + kHaierAcYrw02SwingHLeft, + kHaierAcYrw02SwingHMiddle, + kHaierAcYrw02SwingHRight, + kHaierAcYrw02SwingHRightMax, + // Below are unused. + kHaierAcYrw02SwingHMiddle, + kHaierAcYrw02SwingHMiddle, + kHaierAcYrw02SwingHMiddle, + kHaierAcYrw02SwingHMiddle, + kHaierAcYrw02SwingHMiddle); result += addBoolToString(_.Sleep, kSleepStr); result += addBoolToString(_.Health, kHealthStr); const uint8_t tmode = getTimerMode(); @@ -1098,6 +1285,7 @@ String IRHaierAC176::toString(void) const { result += addLabeledString((tmode != kHaierAcYrw02NoTimers && tmode != kHaierAcYrw02OnTimer) ? minsToString(getOffTimer()) : kOffStr, kOffTimerStr); + result += addBoolToString(_.Lock, kLockStr); return result; } // End of IRHaierAC176 class. @@ -1203,7 +1391,7 @@ bool IRrecv::decodeHaierACYRW02(decode_results* results, uint16_t offset, // Compliance if (strict) { - if (results->state[0] != kHaierAcYrw02Prefix) return false; + if (results->state[0] != kHaierAcYrw02ModelA) return false; if (!IRHaierACYRW02::validChecksum(results->state, nbits / 8)) return false; } @@ -1236,7 +1424,8 @@ bool IRrecv::decodeHaierAC176(decode_results* results, uint16_t offset, // Compliance if (strict) { - if (results->state[0] != kHaierAcYrw02Prefix) return false; + if ((results->state[0] != kHaierAcYrw02ModelA) && + (results->state[0] != kHaierAcYrw02ModelB)) return false; if (!IRHaierAC176::validChecksum(results->state, nbits / 8)) return false; } diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Haier.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Haier.h index 2e287cd12..4e5c8e64c 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Haier.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Haier.h @@ -1,4 +1,4 @@ -// Copyright 2018 crankyoldgit +// Copyright 2018-2021 crankyoldgit /// @file /// @brief Support for Haier A/C protocols. /// The specifics of reverse engineering the protocols details: @@ -13,8 +13,10 @@ // Brand: Haier, Model: HSU07-HEA03 remote (HAIER_AC) // Brand: Haier, Model: YR-W02 remote (HAIER_AC_YRW02) // Brand: Haier, Model: HSU-09HMC203 A/C (HAIER_AC_YRW02) +// Brand: Haier, Model: V9014557 M47 8D remote (HAIER_AC176) // Brand: Mabe, Model: MMI18HDBWCA6MI8 A/C (HAIER_AC176) // Brand: Mabe, Model: V12843 HJ200223 remote (HAIER_AC176) +// Brand: Daichi, Model: D-H A/C (HAIER_AC176) #ifndef IR_HAIER_H_ #define IR_HAIER_H_ @@ -41,7 +43,7 @@ union HaierProtocol{ // Byte 2 uint8_t CurrHours:5; uint8_t unknown :1; // value=1 - uint8_t Swing :2; + uint8_t SwingV :2; // Byte 3 uint8_t CurrMins:6; uint8_t OffTimer:1; @@ -84,10 +86,10 @@ const uint8_t kHaierAcCmdTimerCancel = 0b1010; const uint8_t kHaierAcCmdHealth = 0b1100; const uint8_t kHaierAcCmdSwing = 0b1101; -const uint8_t kHaierAcSwingOff = 0b00; -const uint8_t kHaierAcSwingUp = 0b01; -const uint8_t kHaierAcSwingDown = 0b10; -const uint8_t kHaierAcSwingChg = 0b11; +const uint8_t kHaierAcSwingVOff = 0b00; +const uint8_t kHaierAcSwingVUp = 0b01; +const uint8_t kHaierAcSwingVDown = 0b10; +const uint8_t kHaierAcSwingVChg = 0b11; const uint8_t kHaierAcAuto = 0; const uint8_t kHaierAcCool = 1; @@ -118,11 +120,11 @@ const uint8_t kHaierAcSleepBit = 0b01000000; #define HAIER_AC_CMD_TIMER_SET kHaierAcCmdTimerSet #define HAIER_AC_CMD_TIMER_CANCEL kHaierAcCmdTimerCancel #define HAIER_AC_CMD_HEALTH kHaierAcCmdHealth -#define HAIER_AC_CMD_SWING kHaierAcCmdSwing -#define HAIER_AC_SWING_OFF kHaierAcSwingOff -#define HAIER_AC_SWING_UP kHaierAcSwingUp -#define HAIER_AC_SWING_DOWN kHaierAcSwingDown -#define HAIER_AC_SWING_CHG kHaierAcSwingChg +#define HAIER_AC_CMD_SWINGV kHaierAcCmdSwing +#define HAIER_AC_SWINGV_OFF kHaierAcSwingVOff +#define HAIER_AC_SWINGV_UP kHaierAcSwingVUp +#define HAIER_AC_SWINGV_DOWN kHaierAcSwingVDown +#define HAIER_AC_SWINGV_CHG kHaierAcSwingVChg #define HAIER_AC_AUTO kHaierAcAuto #define HAIER_AC_COOL kHaierAcCool #define HAIER_AC_DRY kHaierAcDry @@ -133,85 +135,54 @@ const uint8_t kHaierAcSleepBit = 0b01000000; #define HAIER_AC_FAN_MED kHaierAcFanMed #define HAIER_AC_FAN_HIGH kHaierAcFanHigh -/// Native representation of a Haier YRW02 A/C message. -union HaierYRW02Protocol{ - uint8_t raw[kHaierACYRW02StateLength]; ///< The state in native form - struct { - // Byte 0 - uint8_t Prefix; - // Byte 1 - uint8_t Swing:4; - uint8_t Temp :4; // 16C~30C - // Byte 2 - uint8_t :8; - // Byte 3 - uint8_t :1; - uint8_t Health:1; - uint8_t :6; - // Byte 4 - uint8_t :6; - uint8_t Power:1; - uint8_t :1; - // Byte 5 - uint8_t :5; - uint8_t Fan:3; - // Byte 6 - uint8_t :6; - uint8_t Turbo:2; - // Byte 7 - uint8_t :5; - uint8_t Mode:3; - // Byte 8 - uint8_t :7; - uint8_t Sleep:1; - // Byte 9 - uint8_t :8; - // Byte 10 - uint8_t :8; - // Byte 11 - uint8_t :8; - // Byte 12 - uint8_t Button:4; - uint8_t :4; - // Byte 13 - uint8_t Sum; - }; -}; +const uint8_t kHaierAcYrw02MinTempC = 16; +const uint8_t kHaierAcYrw02MaxTempC = 30; +const uint8_t kHaierAcYrw02MinTempF = 60; +const uint8_t kHaierAcYrw02MaxTempF = 86; +const uint8_t kHaierAcYrw02DefTempC = 25; -const uint8_t kHaierAcYrw02Prefix = 0xA6; +const uint8_t kHaierAcYrw02ModelA = 0xA6; +const uint8_t kHaierAcYrw02ModelB = 0x59; const uint8_t kHaierAc176Prefix = 0xB7; -const uint8_t kHaierAcYrw02SwingOff = 0x0; -const uint8_t kHaierAcYrw02SwingTop = 0x1; -const uint8_t kHaierAcYrw02SwingMiddle = 0x2; // Not available in heat mode. -const uint8_t kHaierAcYrw02SwingBottom = 0x3; // Only available in heat mode. -const uint8_t kHaierAcYrw02SwingDown = 0xA; -const uint8_t kHaierAcYrw02SwingAuto = 0xC; // Airflow +const uint8_t kHaierAcYrw02SwingVOff = 0x0; +const uint8_t kHaierAcYrw02SwingVTop = 0x1; +const uint8_t kHaierAcYrw02SwingVMiddle = 0x2; // Not available in heat mode. +const uint8_t kHaierAcYrw02SwingVBottom = 0x3; // Only available in heat mode. +const uint8_t kHaierAcYrw02SwingVDown = 0xA; +const uint8_t kHaierAcYrw02SwingVAuto = 0xC; // Airflow + +const uint8_t kHaierAcYrw02SwingHMiddle = 0x0; +const uint8_t kHaierAcYrw02SwingHLeftMax = 0x3; +const uint8_t kHaierAcYrw02SwingHLeft = 0x4; +const uint8_t kHaierAcYrw02SwingHRight = 0x5; +const uint8_t kHaierAcYrw02SwingHRightMax = 0x6; +const uint8_t kHaierAcYrw02SwingHAuto = 0x7; const uint8_t kHaierAcYrw02FanHigh = 0b001; const uint8_t kHaierAcYrw02FanMed = 0b010; const uint8_t kHaierAcYrw02FanLow = 0b011; const uint8_t kHaierAcYrw02FanAuto = 0b101; // HAIER_AC176 uses `0` in Fan2 -const uint8_t kHaierAcYrw02TurboOff = 0x0; -const uint8_t kHaierAcYrw02TurboHigh = 0x1; -const uint8_t kHaierAcYrw02TurboLow = 0x2; - const uint8_t kHaierAcYrw02Auto = 0b000; // 0 const uint8_t kHaierAcYrw02Cool = 0b001; // 1 const uint8_t kHaierAcYrw02Dry = 0b010; // 2 const uint8_t kHaierAcYrw02Heat = 0b100; // 4 const uint8_t kHaierAcYrw02Fan = 0b110; // 5 -const uint8_t kHaierAcYrw02ButtonTempUp = 0x0; -const uint8_t kHaierAcYrw02ButtonTempDown = 0x1; -const uint8_t kHaierAcYrw02ButtonSwing = 0x2; -const uint8_t kHaierAcYrw02ButtonFan = 0x4; -const uint8_t kHaierAcYrw02ButtonPower = 0x5; -const uint8_t kHaierAcYrw02ButtonMode = 0x6; -const uint8_t kHaierAcYrw02ButtonHealth = 0x7; -const uint8_t kHaierAcYrw02ButtonTurbo = 0x8; -const uint8_t kHaierAcYrw02ButtonSleep = 0xB; +const uint8_t kHaierAcYrw02ButtonTempUp = 0b00000; +const uint8_t kHaierAcYrw02ButtonTempDown = 0b00001; +const uint8_t kHaierAcYrw02ButtonSwingV = 0b00010; +const uint8_t kHaierAcYrw02ButtonSwingH = 0b00011; +const uint8_t kHaierAcYrw02ButtonFan = 0b00100; +const uint8_t kHaierAcYrw02ButtonPower = 0b00101; +const uint8_t kHaierAcYrw02ButtonMode = 0b00110; +const uint8_t kHaierAcYrw02ButtonHealth = 0b00111; +const uint8_t kHaierAcYrw02ButtonTurbo = 0b01000; +const uint8_t kHaierAcYrw02ButtonSleep = 0b01011; +const uint8_t kHaierAcYrw02ButtonTimer = 0b10000; +const uint8_t kHaierAcYrw02ButtonLock = 0b10100; +const uint8_t kHaierAcYrw02ButtonCFAB = 0b11010; const uint8_t kHaierAcYrw02NoTimers = 0b000; const uint8_t kHaierAcYrw02OffTimer = 0b001; @@ -224,12 +195,13 @@ union HaierAc176Protocol{ uint8_t raw[kHaierAC176StateLength]; ///< The state in native form struct { // Byte 0 - uint8_t Prefix :8; + uint8_t Model :8; // Byte 1 - uint8_t Swing :4; + uint8_t SwingV :4; uint8_t Temp :4; // 16C~30C // Byte 2 - uint8_t :8; + uint8_t :5; + uint8_t SwingH :3; // Byte 3 uint8_t :1; uint8_t Health :1; @@ -244,7 +216,8 @@ union HaierAc176Protocol{ uint8_t Fan :3; // Byte 6 uint8_t OffTimerMins:6; - uint8_t Turbo:2; + uint8_t Turbo :1; + uint8_t Quiet :1; // Byte 7 uint8_t OnTimerHrs :5; uint8_t Mode :3; @@ -255,12 +228,16 @@ union HaierAc176Protocol{ // Byte 9 uint8_t :8; // Byte 10 - uint8_t :8; + uint8_t ExtraDegreeF :1; + uint8_t :4; + uint8_t UseFahrenheit:1; + uint8_t :2; // Byte 11 uint8_t :8; // Byte 12 - uint8_t Button :4; - uint8_t :4; + uint8_t Button :5; + uint8_t Lock :1; + uint8_t :2; // Byte 13 uint8_t Sum :8; // Byte 14 @@ -295,8 +272,6 @@ union HaierAc176Protocol{ #define HAIER_AC_YRW02_FAN_LOW kHaierAcYrw02FanLow #define HAIER_AC_YRW02_FAN_AUTO kHaierAcYrw02FanAuto #define HAIER_AC_YRW02_TURBO_OFF kHaierAcYrw02TurboOff -#define HAIER_AC_YRW02_TURBO_HIGH kHaierAcYrw02TurboHigh -#define HAIER_AC_YRW02_TURBO_LOW kHaierAcYrw02TurboLow #define HAIER_AC_YRW02_AUTO kHaierAcYrw02Auto #define HAIER_AC_YRW02_COOL kHaierAcYrw02Cool #define HAIER_AC_YRW02_DRY kHaierAcYrw02Dry @@ -355,8 +330,8 @@ class IRHaierAC { uint16_t getCurrTime(void) const; void setCurrTime(const uint16_t mins); - uint8_t getSwing(void) const; - void setSwing(const uint8_t state); + uint8_t getSwingV(void) const; + void setSwingV(const uint8_t state); uint8_t* getRaw(void); void setRaw(const uint8_t new_code[]); @@ -400,10 +375,15 @@ class IRHaierAC176 { void begin(void); void stateReset(void); + void setModel(const haier_ac176_remote_model_t model); + haier_ac176_remote_model_t getModel(void) const; + void setButton(const uint8_t button); uint8_t getButton(void) const; - void setTemp(const uint8_t temp); + void setUseFahrenheit(const bool on); + bool getUseFahrenheit(void) const; + void setTemp(const uint8_t temp, const bool fahrenheit = false); uint8_t getTemp(void) const; void setFan(const uint8_t speed); @@ -422,9 +402,18 @@ class IRHaierAC176 { bool getHealth(void) const; void setHealth(const bool on); - uint8_t getTurbo(void) const; - void setTurbo(const uint8_t speed); + bool getTurbo(void) const; + void setTurbo(const bool on); + bool getQuiet(void) const; + void setQuiet(const bool on); + uint8_t getSwingV(void) const; + void setSwingV(const uint8_t pos); + uint8_t getSwingH(void) const; + void setSwingH(const uint8_t pos); + + /// These functions are for backward compatibility. + /// Use getSwingV() and setSwingV() instead. uint8_t getSwing(void) const; void setSwing(const uint8_t pos); @@ -435,6 +424,9 @@ class IRHaierAC176 { void setOffTimer(const uint16_t mins); uint16_t getOffTimer(void) const; + bool getLock(void) const; + void setLock(const bool on); + uint8_t* getRaw(void); virtual void setRaw(const uint8_t new_code[]); static bool validChecksum(const uint8_t state[], @@ -442,9 +434,13 @@ class IRHaierAC176 { static uint8_t convertMode(const stdAc::opmode_t mode); static uint8_t convertFan(const stdAc::fanspeed_t speed); static uint8_t convertSwingV(const stdAc::swingv_t position); + static uint8_t convertSwingH(const stdAc::swingh_t position); static stdAc::opmode_t toCommonMode(const uint8_t mode); static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed); static stdAc::swingv_t toCommonSwingV(const uint8_t pos); + static stdAc::swingh_t toCommonSwingH(const uint8_t pos); + static bool toCommonTurbo(const uint8_t speed); + static bool toCommonQuiet(const uint8_t speed); stdAc::state_t toCommon(void) const; String toString(void) const; #ifndef UNIT_TEST diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_LG.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_LG.h index 6010282ca..2bd7dbc1c 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_LG.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_LG.h @@ -15,6 +15,8 @@ // Brand: LG, Model: AMNW09GSJA0 A/C (LG2 - AKB74955603) // Brand: LG, Model: AMNW24GTPA1 A/C (LG2 - AKB73757604) // Brand: LG, Model: AKB73757604 remote (LG2 - AKB73757604) +// Brand: LG, Model: AKB73315611 remote (LG2 - AKB74955603) +// Brand: LG, Model: MS05SQ NW0 A/C (LG2 - AKB74955603) // Brand: General Electric, Model: AG1BH09AW101 Split A/C (LG) // Brand: General Electric, Model: 6711AR2853M A/C Remote (LG) diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Mirage.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Mirage.cpp index 8a573a8dc..a806937b1 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Mirage.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Mirage.cpp @@ -1,15 +1,35 @@ -// Copyright 2020 David Conran (crankyoldgit) +// Copyright 2020-2021 David Conran (crankyoldgit) /// @file /// @brief Support for Mirage protocol /// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1289 +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1573 -// Supports: -// Brand: Mirage, Model: VLU series A/C +#include "ir_Mirage.h" +#include +#include +#ifndef ARDUINO +#include +#endif #include "IRrecv.h" #include "IRsend.h" +#include "IRtext.h" #include "IRutils.h" +using irutils::addBoolToString; +using irutils::addFanToString; +using irutils::addIntToString; +using irutils::addLabeledString; +using irutils::addModeToString; +using irutils::addModelToString; +using irutils::addSwingHToString; +using irutils::addSwingVToString; +using irutils::addTempToString; +using irutils::addToggleToString; +using irutils::minsToString; +using irutils::bcdToUint8; +using irutils::uint8ToBcd; +using irutils::sumNibbles; // Constants const uint16_t kMirageHdrMark = 8360; ///< uSeconds @@ -20,6 +40,9 @@ const uint16_t kMirageZeroSpace = 545; ///< uSeconds const uint32_t kMirageGap = kDefaultMessageGap; ///< uSeconds (just a guess) const uint16_t kMirageFreq = 38000; ///< Hz. (Just a guess) +const uint8_t kMirageAcKKG29AC1PowerOn = 0b00; // 0 +const uint8_t kMirageAcKKG29AC1PowerOff = 0b11; // 3 + #if SEND_MIRAGE /// Send a Mirage formatted message. @@ -58,6 +81,8 @@ bool IRrecv::decodeMirage(decode_results *results, uint16_t offset, kMirageBitMark, kMirageZeroSpace, kMirageBitMark, kMirageGap, true, kUseDefTol, kMarkExcess, false)) return false; + // Compliance + if (strict && !IRMirageAc::validChecksum(results->state)) return false; // Success results->decode_type = decode_type_t::MIRAGE; @@ -67,4 +92,756 @@ bool IRrecv::decodeMirage(decode_results *results, uint16_t offset, // is a union data type. return true; } + +// Code to emulate Mirage A/C IR remote control unit. + +/// Class constructor +/// @param[in] pin GPIO to be used when sending. +/// @param[in] inverted Is the output signal to be inverted? +/// @param[in] use_modulation Is frequency modulation to be used? +IRMirageAc::IRMirageAc(const uint16_t pin, const bool inverted, + const bool use_modulation) + : _irsend(pin, inverted, use_modulation) { stateReset(); } + +/// Reset the state of the remote to a known good state/sequence. +void IRMirageAc::stateReset(void) { + // The state of the IR remote in IR code form. + static const uint8_t kReset[kMirageStateLength] = { + 0x56, 0x6C, 0x00, 0x00, 0x20, 0x1A, 0x00, 0x00, + 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x42}; + setRaw(kReset); + _model = mirage_ac_remote_model_t::KKG9AC1; +} + +/// Set up hardware to be able to send a message. +void IRMirageAc::begin(void) { _irsend.begin(); } + +#if SEND_MITSUBISHI_AC +/// Send the current internal state as an IR message. +/// @param[in] repeat Nr. of times the message will be repeated. +void IRMirageAc::send(const uint16_t repeat) { + _irsend.sendMirage(getRaw(), kMirageStateLength, repeat); + // Reset any toggles after a send. + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: + setCleanToggle(false); + setLight(false); // For this model (only), Light is a toggle. + break; + default: + break; + } +} +#endif // SEND_MITSUBISHI_AC + +/// Get a PTR to the internal state/code for this protocol. +/// @return PTR to a code for this protocol based on the current internal state. +uint8_t *IRMirageAc::getRaw(void) { + checksum(); + return _.raw; +} + +/// Set the internal state from a valid code for this protocol. +/// @param[in] data A valid code for this protocol. +void IRMirageAc::setRaw(const uint8_t *data) { + std::memcpy(_.raw, data, kMirageStateLength); + _model = getModel(true); +} + +/// Guess the Mirage remote model from the supplied state code. +/// @param[in] state A valid state code for this protocol. +/// @return The model code. +/// @note This result isn't perfect. Both protocols can look the same but have +/// wildly different settings. +mirage_ac_remote_model_t IRMirageAc::getModel(const uint8_t *state) { + Mirage120Protocol p; + std::memcpy(p.raw, state, kMirageStateLength); + // Check for KKG29AC1 specific settings. + if (p.RecycleHeat || p.Filter || p.Sleep_Kkg29ac1 || p.CleanToggle || + p.IFeel || p.OffTimerEnable || p.OnTimerEnable) + return mirage_ac_remote_model_t::KKG29AC1; + // Check for things specific to KKG9AC1 + if ((p.Minutes || p.Seconds) || // Is part of the clock set? + // Are the timer times set, but not enabled? (enable check filtered above) + (p.OffTimerHours || p.OffTimerMins) || + (p.OnTimerHours || p.OnTimerMins)) + return mirage_ac_remote_model_t::KKG9AC1; + // As the above test has a 1 in 3600+ (for 1 second an hour) chance of a false + // negative in theory, we are going assume that anything left should be a + // KKG29AC1 model. + return mirage_ac_remote_model_t::KKG29AC1; // Default. +} + +/// Get the model code of the interal message state. +/// @param[in] useRaw If set, we try to get the model info from just the state. +/// @return The model code. +mirage_ac_remote_model_t IRMirageAc::getModel(const bool useRaw) const { + return useRaw ? getModel(_.raw) : _model; +} + +/// Set the model code of the interal message state. +/// @param[in] model The desired model to use for the settings. +void IRMirageAc::setModel(const mirage_ac_remote_model_t model) { + if (model != _model) { // Only change things if we need to. + // Save the old settings. + stdAc::state_t state = toCommon(); + const uint16_t ontimer = getOnTimer(); + const uint16_t offtimer = getOffTimer(); + const bool ifeel = getIFeel(); + const uint8_t sensor = getSensorTemp(); + // Change the model. + state.model = model; + // Restore/Convert the settings. + fromCommon(state); + setOnTimer(ontimer); + setOffTimer(offtimer); + setIFeel(ifeel); + setSensorTemp(sensor); + } +} + +/// Calculate and set the checksum values for the internal state. +void IRMirageAc::checksum(void) { _.Sum = calculateChecksum(_.raw); } + +/// Verify the checksum is valid for a given state. +/// @param[in] data The array to verify the checksum of. +/// @return true, if the state has a valid checksum. Otherwise, false. +bool IRMirageAc::validChecksum(const uint8_t *data) { + return calculateChecksum(data) == data[kMirageStateLength - 1]; +} + +/// Calculate the checksum for a given state. +/// @param[in] data The value to calc the checksum of. +/// @return The calculated checksum value. +uint8_t IRMirageAc::calculateChecksum(const uint8_t *data) { + return sumNibbles(data, kMirageStateLength - 1); +} + +/// Set the requested power state of the A/C to on. +void IRMirageAc::on(void) { setPower(true); } + +/// Set the requested power state of the A/C to off. +void IRMirageAc::off(void) { setPower(false); } + +/// Change the power setting. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRMirageAc::setPower(bool on) { + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: + _.Power = on ? kMirageAcKKG29AC1PowerOn : kMirageAcKKG29AC1PowerOff; + break; + default: + // In order to change the power setting, it seems must be less than + // kMirageAcPowerOff. kMirageAcPowerOff is larger than half of the + // possible value stored in the allocated bit space. + // Thus if the value is larger than kMirageAcPowerOff the power is off. + // Less than, then power is on. + // We can't just aribitarily add or subtract the value (which analysis + // indicates is how the power status changes. Very weird, I know!) as that + // is not an idempotent action, we must check if the addition or + // substraction is needed first. e.g. via getPower() + // i.e. If we added or subtracted twice, we would cause a wrap of the + // integer and not get the desired result. + if (on) + _.SwingAndPower -= getPower() ? 0 : kMirageAcPowerOff; + else + _.SwingAndPower += getPower() ? kMirageAcPowerOff : 0; + } +} + +/// Get the value of the current power setting. +/// @return true, the setting is on. false, the setting is off. +bool IRMirageAc::getPower(void) const { + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: + return _.Power == kMirageAcKKG29AC1PowerOn; + default: + return _.SwingAndPower < kMirageAcPowerOff; + } +} + +/// Get the operating mode setting of the A/C. +/// @return The current operating mode setting. +uint8_t IRMirageAc::getMode(void) const { return _.Mode; } + +/// Set the operating mode of the A/C. +/// @param[in] mode The desired operating mode. +void IRMirageAc::setMode(const uint8_t mode) { + switch (mode) { + case kMirageAcCool: + case kMirageAcDry: + case kMirageAcHeat: + case kMirageAcFan: + case kMirageAcRecycle: + _.Mode = mode; + // Reset turbo if we have to. + setTurbo(getTurbo()); + break; + default: // Default to cool mode for anything else. + setMode(kMirageAcCool); + } +} + +/// Set the temperature. +/// @param[in] degrees The temperature in degrees celsius. +void IRMirageAc::setTemp(const uint8_t degrees) { + // Make sure we have desired temp in the correct range. + uint8_t celsius = std::max(degrees, kMirageAcMinTemp); + _.Temp = std::min(celsius, kMirageAcMaxTemp) + kMirageAcTempOffset; +} + +/// Get the current temperature setting. +/// @return The current setting for temp. in degrees celsius. +uint8_t IRMirageAc::getTemp(void) const { return _.Temp - kMirageAcTempOffset; } + +/// Set the speed of the fan. +/// @param[in] speed The desired setting. +void IRMirageAc::setFan(const uint8_t speed) { + _.Fan = (speed <= kMirageAcFanLow) ? speed : kMirageAcFanAuto; +} + +/// Get the current fan speed setting. +/// @return The current fan speed/mode. +uint8_t IRMirageAc::getFan(void) const { return _.Fan; } + +/// Change the Turbo setting. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRMirageAc::setTurbo(bool on) { + const bool value = (on && (getMode() == kMirageAcCool)); + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: + _.Turbo_Kkg29ac1 = value; + break; + default: + _.Turbo_Kkg9ac1 = value; + } +} + +/// Get the value of the current Turbo setting. +/// @return true, the setting is on. false, the setting is off. +bool IRMirageAc::getTurbo(void) const { + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: return _.Turbo_Kkg29ac1; + default: return _.Turbo_Kkg9ac1; + } +} + +/// Change the Sleep setting. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRMirageAc::setSleep(bool on) { + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: + _.Sleep_Kkg29ac1 = on; + break; + default: + _.Sleep_Kkg9ac1 = on; + } +} + +/// Get the value of the current Sleep setting. +/// @return true, the setting is on. false, the setting is off. +bool IRMirageAc::getSleep(void) const { + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: return _.Sleep_Kkg29ac1; + default: return _.Sleep_Kkg9ac1; + } +} + +/// Change the Light/Display setting. +/// @param[in] on true, the setting is on. false, the setting is off. +/// @note Light is a toggle on the KKG29AC1 model. +void IRMirageAc::setLight(bool on) { + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: + _.LightToggle_Kkg29ac1 = on; + break; + default: + _.Light_Kkg9ac1 = on; + } +} + +/// Get the value of the current Light/Display setting. +/// @return true, the setting is on. false, the setting is off. +/// @note Light is a toggle on the KKG29AC1 model. +bool IRMirageAc::getLight(void) const { + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: return _.LightToggle_Kkg29ac1; + default: return _.Light_Kkg9ac1; + } +} + +/// Get the clock time of the A/C unit. +/// @return Nr. of seconds past midnight. +uint32_t IRMirageAc::getClock(void) const { + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: + return 0; + default: + return ((bcdToUint8(_.Hours) * 60) + bcdToUint8(_.Minutes)) * 60 + + bcdToUint8(_.Seconds); + } +} + +/// Set the clock time on the A/C unit. +/// @param[in] nr_of_seconds Nr. of seconds past midnight. +void IRMirageAc::setClock(const uint32_t nr_of_seconds) { + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: + _.Minutes = _.Seconds = 0; // No clock setting. Clear it just in case. + break; + default: + uint32_t remaining = std::min( + nr_of_seconds, (uint32_t)(24 * 60 * 60 - 1)); // Limit to 23:59:59. + _.Seconds = uint8ToBcd(remaining % 60); + remaining /= 60; + _.Minutes = uint8ToBcd(remaining % 60); + remaining /= 60; + _.Hours = uint8ToBcd(remaining); + } +} + +/// Set the Vertical Swing setting/position of the A/C. +/// @param[in] position The desired swing setting. +void IRMirageAc::setSwingV(const uint8_t position) { + switch (position) { + case kMirageAcSwingVOff: + case kMirageAcSwingVLowest: + case kMirageAcSwingVLow: + case kMirageAcSwingVMiddle: + case kMirageAcSwingVHigh: + case kMirageAcSwingVHighest: + case kMirageAcSwingVAuto: + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: + _.SwingV = (position != kMirageAcSwingVOff); + break; + default: + const bool power = getPower(); + _.SwingAndPower = position; + // Power needs to be reapplied after overwriting SwingAndPower + setPower(power); + } + break; + default: // Default to Auto for anything else. + setSwingV(kMirageAcSwingVAuto); + } +} + +/// Get the Vertical Swing setting/position of the A/C. +/// @return The desired Vertical Swing setting/position. +uint8_t IRMirageAc::getSwingV(void) const { + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: + return _.SwingV ? kMirageAcSwingVAuto : kMirageAcSwingVOff; + default: + return _.SwingAndPower - (getPower() ? 0 : kMirageAcPowerOff); + } +} + +/// Set the Horizontal Swing setting of the A/C. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRMirageAc::setSwingH(const bool on) { + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: + _.SwingH = on; + break; + default: + break; + } +} + +/// Get the Horizontal Swing setting of the A/C. +/// @return on true, the setting is on. false, the setting is off. +bool IRMirageAc::getSwingH(void) const { + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: return _.SwingH; + default: return false; + } +} + +/// Set the Quiet setting of the A/C. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRMirageAc::setQuiet(const bool on) { + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: + _.Quiet = on; + break; + default: + break; + } +} + +/// Get the Quiet setting of the A/C. +/// @return on true, the setting is on. false, the setting is off. +bool IRMirageAc::getQuiet(void) const { + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: return _.Quiet; + default: return false; + } +} + +/// Set the CleanToggle setting of the A/C. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRMirageAc::setCleanToggle(const bool on) { + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: + _.CleanToggle = on; + break; + default: + break; + } +} + +/// Get the Clean Toggle setting of the A/C. +/// @return on true, the setting is on. false, the setting is off. +bool IRMirageAc::getCleanToggle(void) const { + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: return _.CleanToggle; + default: return false; + } +} + +/// Set the Filter setting of the A/C. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRMirageAc::setFilter(const bool on) { + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: + _.Filter = on; + break; + default: + break; + } +} + +/// Get the Filter setting of the A/C. +/// @return on true, the setting is on. false, the setting is off. +bool IRMirageAc::getFilter(void) const { + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: return _.Filter; + default: return false; + } +} + +/// Set the IFeel setting of the A/C. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRMirageAc::setIFeel(const bool on) { + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: + _.IFeel = on; + if (on) { + // If no previous sensor temp, default to currently desired temp. + if (!_.SensorTemp) _.SensorTemp = getTemp(); + } else { + _.SensorTemp = 0; // When turning it off, clear the Sensor Temp. + } + break; + default: + break; + } +} + +/// Get the IFeel setting of the A/C. +/// @return on true, the setting is on. false, the setting is off. +bool IRMirageAc::getIFeel(void) const { + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: return _.IFeel; + default: return false; + } +} + +/// Set the Sensor Temp setting of the A/C's remote. +/// @param[in] degrees The desired sensor temp. in degrees celsius. +void IRMirageAc::setSensorTemp(const uint8_t degrees) { + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: + _.SensorTemp = std::min(kMirageAcSensorTempMax, degrees) + + kMirageAcSensorTempOffset; + break; + default: + break; + } +} + +/// Get the Sensor Temp setting of the A/C's remote. +/// @return The current setting for the sensor temp. in degrees celsius. +uint16_t IRMirageAc::getSensorTemp(void) const { + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: + return _.SensorTemp - kMirageAcSensorTempOffset; + default: + return false; + } +} + +/// Get the number of minutes the On Timer is currently set for. +/// @return Nr. of Minutes the timer is set for. 0, is the timer is not in use. +uint16_t IRMirageAc::getOnTimer(void) const { + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: + return _.OnTimerEnable ? _.OnTimerHours * 60 + _.OnTimerMins : 0; + default: + return 0; + } +} + +/// Set the number of minutes for the On Timer. +/// @param[in] nr_of_mins How long to set the timer for. 0 disables the timer. +void IRMirageAc::setOnTimer(const uint16_t nr_of_mins) { + uint16_t mins = std::min(nr_of_mins, (uint16_t)(24 * 60)); + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: + _.OnTimerEnable = (mins > 0); + _.OnTimerHours = mins / 60; + _.OnTimerMins = mins % 60; + break; + default: + break; + } +} + +/// Get the number of minutes the Off Timer is currently set for. +/// @return Nr. of Minutes the timer is set for. 0, is the timer is not in use. +uint16_t IRMirageAc::getOffTimer(void) const { + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: + return _.OffTimerEnable ? _.OffTimerHours * 60 + _.OffTimerMins : 0; + default: + return 0; + } +} + +/// Set the number of minutes for the Off Timer. +/// @param[in] nr_of_mins How long to set the timer for. 0 disables the timer. +void IRMirageAc::setOffTimer(const uint16_t nr_of_mins) { + uint16_t mins = std::min(nr_of_mins, (uint16_t)(24 * 60)); + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: + _.OffTimerEnable = (mins > 0); + _.OffTimerHours = mins / 60; + _.OffTimerMins = mins % 60; + break; + default: + break; + } +} + +/// Convert a native mode into its stdAc equivalent. +/// @param[in] mode The native setting to be converted. +/// @return The stdAc equivalent of the native setting. +stdAc::opmode_t IRMirageAc::toCommonMode(const uint8_t mode) { + switch (mode) { + case kMirageAcHeat: return stdAc::opmode_t::kHeat; + case kMirageAcDry: return stdAc::opmode_t::kDry; + case kMirageAcFan: return stdAc::opmode_t::kFan; + default: return stdAc::opmode_t::kCool; + } +} + +/// Convert a native fan speed into its stdAc equivalent. +/// @param[in] speed The native setting to be converted. +/// @param[in] model The model type to use to influence the conversion. +/// @return The stdAc equivalent of the native setting. +stdAc::fanspeed_t IRMirageAc::toCommonFanSpeed(const uint8_t speed, + const mirage_ac_remote_model_t model) { + switch (model) { + case mirage_ac_remote_model_t::KKG29AC1: + switch (speed) { + case kMirageAcKKG29AC1FanHigh: return stdAc::fanspeed_t::kHigh; + case kMirageAcKKG29AC1FanMed: return stdAc::fanspeed_t::kMedium; + case kMirageAcKKG29AC1FanLow: return stdAc::fanspeed_t::kLow; + default: return stdAc::fanspeed_t::kAuto; + } + break; + default: + switch (speed) { + case kMirageAcFanHigh: return stdAc::fanspeed_t::kHigh; + case kMirageAcFanMed: return stdAc::fanspeed_t::kMedium; + case kMirageAcFanLow: return stdAc::fanspeed_t::kLow; + default: return stdAc::fanspeed_t::kAuto; + } + } +} + +/// Convert a stdAc::opmode_t enum into its native mode. +/// @param[in] mode The enum to be converted. +/// @return The native equivalent of the enum. +uint8_t IRMirageAc::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kHeat: return kMirageAcHeat; + case stdAc::opmode_t::kDry: return kMirageAcDry; + case stdAc::opmode_t::kFan: return kMirageAcFan; + default: return kMirageAcCool; + } +} + +/// Convert a stdAc::fanspeed_t enum into it's native speed. +/// @param[in] speed The enum to be converted. +/// @param[in] model The model type to use to influence the conversion. +/// @return The native equivalent of the enum. +uint8_t IRMirageAc::convertFan(const stdAc::fanspeed_t speed, + const mirage_ac_remote_model_t model) { + uint8_t low; + uint8_t med; + switch (model) { + case mirage_ac_remote_model_t::KKG29AC1: + low = kMirageAcKKG29AC1FanLow; + med = kMirageAcKKG29AC1FanMed; + break; + default: + low = kMirageAcFanLow; + med = kMirageAcFanMed; + } + switch (speed) { + case stdAc::fanspeed_t::kMin: + case stdAc::fanspeed_t::kLow: return low; + case stdAc::fanspeed_t::kMedium: return med; + case stdAc::fanspeed_t::kHigh: + case stdAc::fanspeed_t::kMax: return kMirageAcFanHigh; + default: return kMirageAcFanAuto; + } +} + +/// Convert a stdAc::swingv_t enum into it's native setting. +/// @param[in] position The enum to be converted. +/// @return The native equivalent of the enum. +uint8_t IRMirageAc::convertSwingV(const stdAc::swingv_t position) { + switch (position) { + case stdAc::swingv_t::kHighest: return kMirageAcSwingVHighest; + case stdAc::swingv_t::kHigh: return kMirageAcSwingVHigh; + case stdAc::swingv_t::kMiddle: return kMirageAcSwingVMiddle; + case stdAc::swingv_t::kLow: return kMirageAcSwingVLow; + case stdAc::swingv_t::kLowest: return kMirageAcSwingVLowest; + case stdAc::swingv_t::kOff: return kMirageAcSwingVOff; + default: return kMirageAcSwingVAuto; + } +} + +/// Convert a native vertical swing postion to it's common equivalent. +/// @param[in] pos A native position to convert. +/// @return The common vertical swing position. +stdAc::swingv_t IRMirageAc::toCommonSwingV(const uint8_t pos) { + switch (pos) { + case kMirageAcSwingVHighest: return stdAc::swingv_t::kHighest; + case kMirageAcSwingVHigh: return stdAc::swingv_t::kHigh; + case kMirageAcSwingVMiddle: return stdAc::swingv_t::kMiddle; + case kMirageAcSwingVLow: return stdAc::swingv_t::kLow; + case kMirageAcSwingVLowest: return stdAc::swingv_t::kLowest; + case kMirageAcSwingVAuto: return stdAc::swingv_t::kAuto; + default: return stdAc::swingv_t::kOff; + } +} + +/// Convert the current internal state into its stdAc::state_t equivalent. +/// @return The stdAc equivalent of the native settings. +stdAc::state_t IRMirageAc::toCommon(void) const { + stdAc::state_t result; + result.protocol = decode_type_t::MIRAGE; + result.model = _model; + result.power = getPower(); + result.mode = toCommonMode(_.Mode); + result.celsius = true; + result.degrees = getTemp(); + result.fanspeed = toCommonFanSpeed(getFan(), _model); + result.swingv = toCommonSwingV(getSwingV()); + result.swingh = getSwingH() ? stdAc::swingh_t::kAuto : stdAc::swingh_t::kOff; + result.turbo = getTurbo(); + result.light = getLight(); + result.clean = getCleanToggle(); + result.filter = getFilter(); + result.sleep = getSleep() ? 0 : -1; + result.quiet = getQuiet(); + result.clock = getClock() / 60; + // Not supported. + result.econo = false; + result.beep = false; + return result; +} + +/// Convert & set a stdAc::state_t to its equivalent internal settings. +/// @param[in] state The desired state in stdAc::state_t form. +void IRMirageAc::fromCommon(const stdAc::state_t state) { + stateReset(); + _model = (mirage_ac_remote_model_t)state.model; // Set directly to avoid loop + setPower(state.power); + setTemp(state.celsius ? state.degrees : fahrenheitToCelsius(state.degrees)); + setMode(convertMode(state.mode)); + setFan(convertFan(state.fanspeed, _model)); + setTurbo(state.turbo); + setSleep(state.sleep >= 0); + setLight(state.light); + setSwingV(convertSwingV(state.swingv)); + setSwingH(state.swingh != stdAc::swingh_t::kOff); + setQuiet(state.quiet); + setCleanToggle(state.clean); + setFilter(state.filter); + // setClock() expects seconds, not minutes. + setClock((state.clock > 0) ? state.clock * 60 : 0); + // Non-common settings. + setOnTimer(0); + setOffTimer(0); + setIFeel(false); +} + +/// Convert the internal state into a human readable string. +/// @return A string containing the settings in human-readable form. +String IRMirageAc::toString(void) const { + String result = ""; + result.reserve(240); // Reserve some heap for the string to reduce fragging. + result += addModelToString(decode_type_t::MIRAGE, _model, false); + result += addBoolToString(getPower(), kPowerStr); + result += addModeToString(_.Mode, 0xFF, kMirageAcCool, + kMirageAcHeat, kMirageAcDry, + kMirageAcFan); + result += addTempToString(getTemp()); + uint8_t fanlow; + uint8_t fanmed; + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: + fanlow = kMirageAcKKG29AC1FanLow; + fanmed = kMirageAcKKG29AC1FanMed; + break; + default: // e.g. Model KKG9AC1 + fanlow = kMirageAcFanLow; + fanmed = kMirageAcFanMed; + } + result += addFanToString(_.Fan, kMirageAcFanHigh, fanlow, kMirageAcFanAuto, + kMirageAcFanAuto, fanmed); + result += addBoolToString(getTurbo(), kTurboStr); + result += addBoolToString(getSleep(), kSleepStr); + switch (_model) { + case mirage_ac_remote_model_t::KKG29AC1: + result += addBoolToString(_.Quiet, kQuietStr); + result += addToggleToString(getLight(), kLightStr); + result += addBoolToString(_.SwingV, kSwingVStr); + result += addBoolToString(_.SwingH, kSwingHStr); + result += addBoolToString(_.Filter, kFilterStr); + result += addToggleToString(_.CleanToggle, kCleanStr); + result += addLabeledString(getOnTimer() ? minsToString(getOnTimer()) + : kOffStr, + kOnTimerStr); + result += addLabeledString(getOffTimer() ? minsToString(getOffTimer()) + : kOffStr, + kOffTimerStr); + result += addBoolToString(_.IFeel, kIFeelStr); + if (_.IFeel) { + result += addIntToString(getSensorTemp(), kSensorTempStr); + result += 'C'; + } + break; + default: // e.g. Model KKG9AC1 + result += addBoolToString(getLight(), kLightStr); + result += addSwingVToString(getSwingV(), + kMirageAcSwingVAuto, + kMirageAcSwingVHighest, + kMirageAcSwingVHigh, + 0xFF, // Unused. + kMirageAcSwingVMiddle, + 0xFF, // Unused. + kMirageAcSwingVLow, + kMirageAcSwingVLowest, + kMirageAcSwingVOff, + 0xFF, 0xFF, 0xFF); // Unused. + result += addLabeledString(minsToString(getClock() / 60), kClockStr); + } + return result; +} #endif // DECODE_MIRAGE diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Mirage.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Mirage.h new file mode 100644 index 000000000..b2b39e759 --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Mirage.h @@ -0,0 +1,277 @@ +// Copyright 2020-2021 David Conran (crankyoldgit) +/// @file +/// @brief Support for Mirage protocol +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1289 +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1573 + + +// Supports: +// Brand: Mirage, Model: VLU series A/C +// Brand: Maxell, Model: MX-CH18CF A/C +// Brand: Maxell, Model: KKG9A-C1 remote +// Brand: Tronitechnik, Model: Reykir 9000 A/C +// Brand: Tronitechnik, Model: KKG29A-C1 remote + +#ifndef IR_MIRAGE_H_ +#define IR_MIRAGE_H_ + +#define __STDC_LIMIT_MACROS +#include +#ifndef UNIT_TEST +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" +#ifdef UNIT_TEST +#include "IRsend_test.h" +#endif + +/// Native representation of a Mirage 120-bit A/C message. +/// @see https://docs.google.com/spreadsheets/d/1Ucu9mOOIIJoWQjUJq_VCvwgV3EwKaRk8K2AuZgccYEk/edit#gid=0 +union Mirage120Protocol{ + uint8_t raw[kMirageStateLength]; ///< The state in code form. + struct { // Common + // Byte 0 + uint8_t Header :8; // Header. (0x56) + // Byte 1 + uint8_t Temp :8; // Celsius minus 0x5C. + // Byte 2 + uint8_t :8; // Unknown / Unused. + // Byte 3 + uint8_t :8; // Unknown / Unused. + // Byte 4 + uint8_t Fan :2; // Fan Speed. + uint8_t :2; // Unknown / Unused. + uint8_t Mode :4; // Cool, Heat, Dry, Fan, Recycle + // Byte 5 + uint8_t :8; + // Byte 6 + uint8_t :8; + // Byte 7 + uint8_t :8; + // Byte 8 + uint8_t :8; + // Byte 9 + uint8_t :8; + // Byte 10 + uint8_t :8; + // Byte 11 + uint8_t :8; + // Byte 12 + uint8_t :8; + // Byte 13 + uint8_t :8; + // Byte 14 + uint8_t Sum :8; // Sum of all the previous nibbles. + }; + struct { // KKG9AC1 remote + // Byte 0 + uint8_t :8; // Header + // Byte 1 + uint8_t :8; // Temp + // Byte 2 + uint8_t :8; // Unknown / Unused. + // Byte 3 + uint8_t :3; // Unknown / Unused. + uint8_t Light_Kkg9ac1 :1; // Aka. Display. Seems linked to Sleep mode. + uint8_t :4; // Unknown / Unused. + // Byte 4 + uint8_t :8; // Fan & Mode + // Byte 5 + uint8_t :1; // Unknown + uint8_t SwingAndPower :7; + // Byte 6 + uint8_t :7; // Unknown / Unused. + uint8_t Sleep_Kkg9ac1 :1; // Sleep mode on or off. + // Byte 7 + uint8_t :3; // Unknown / Unused. + uint8_t Turbo_Kkg9ac1 :1; // Turbo mode on or off. Only works in Cool mode. + uint8_t :4; // Unknown / Unused. + // Byte 8 + uint8_t :8; // Unknown / Unused. + // Byte 9 + uint8_t :8; // Unknown / Unused. + // Byte 10 + uint8_t :8; // Unknown / Unused. + // Byte 11 + uint8_t Seconds :8; // Nr. of Seconds in BCD. + // Byte 12 + uint8_t Minutes :8; // Nr. of Minutes in BCD. + // Byte 13 + uint8_t Hours :8; // Nr. of Hours in BCD. + // Byte 14 + uint8_t :8; // Sum + }; + struct { // KKG29A-C1 remote + // Byte 0 + uint8_t :8; // Header + // Byte 1 + uint8_t :8; // Temp + // Byte 2 + uint8_t :8; + // Byte 3 + uint8_t Quiet :1; + uint8_t :7; + // Byte 4 + uint8_t :2; // Fan + uint8_t OffTimerEnable :1; + uint8_t OnTimerEnable :1; + uint8_t :3; // Mode + uint8_t :1; + // Byte 5 + uint8_t SwingH :1; + uint8_t SwingV :1; + uint8_t LightToggle_Kkg29ac1 :1; // Aka. Display Toggle. + uint8_t :3; + uint8_t Power :2; + // Byte 6 + uint8_t :1; + uint8_t Filter :1; // Aka. UVC + uint8_t :1; + uint8_t Sleep_Kkg29ac1 :1; // Sleep mode on or off. + uint8_t :2; + uint8_t RecycleHeat :1; + uint8_t :1; + // Byte 7 + uint8_t SensorTemp :6; // Temperature at the remote + uint8_t CleanToggle :1; + uint8_t IFeel :1; + // Byte 8 + uint8_t OnTimerHours :5; + uint8_t :2; + uint8_t Turbo_Kkg29ac1 :1; // Turbo mode on or off. + // Byte 9 + uint8_t OnTimerMins :6; + uint8_t :2; + // Byte 10 + uint8_t OffTimerHours :5; + uint8_t :3; + // Byte 11 + uint8_t OffTimerMins :6; + uint8_t :2; + // Byte 12 + uint8_t :8; + // Byte 13 + uint8_t :8; + // Byte 14 + uint8_t :8; // Sum + }; +}; + +// Constants +const uint8_t kMirageAcHeat = 0b001; // 1 +const uint8_t kMirageAcCool = 0b010; // 2 +const uint8_t kMirageAcDry = 0b011; // 3 +const uint8_t kMirageAcRecycle = 0b100; // 4 +const uint8_t kMirageAcFan = 0b101; // 5 + +const uint8_t kMirageAcFanAuto = 0b00; // 0 +const uint8_t kMirageAcFanHigh = 0b01; // 1 +const uint8_t kMirageAcFanMed = 0b10; // 2 +const uint8_t kMirageAcFanLow = 0b11; // 3 +const uint8_t kMirageAcKKG29AC1FanAuto = 0b00; // 0 +const uint8_t kMirageAcKKG29AC1FanHigh = 0b01; // 1 +const uint8_t kMirageAcKKG29AC1FanLow = 0b10; // 2 +const uint8_t kMirageAcKKG29AC1FanMed = 0b11; // 3 + +const uint8_t kMirageAcMinTemp = 16; // 16C +const uint8_t kMirageAcMaxTemp = 32; // 32C +const uint8_t kMirageAcTempOffset = 0x5C; +const uint8_t kMirageAcSensorTempOffset = 20; +const uint8_t kMirageAcSensorTempMax = 43; // Celsius + +const uint8_t kMirageAcPowerOff = 0x5F; +const uint8_t kMirageAcSwingVOff = 0b0000; // 0 +const uint8_t kMirageAcSwingVLowest = 0b0011; // 3 +const uint8_t kMirageAcSwingVLow = 0b0101; // 5 +const uint8_t kMirageAcSwingVMiddle = 0b0111; // 7 +const uint8_t kMirageAcSwingVHigh = 0b1001; // 9 +const uint8_t kMirageAcSwingVHighest = 0b1011; // 11 +const uint8_t kMirageAcSwingVAuto = 0b1101; // 13 + + +/// Class for handling detailed Mirage 120-bit A/C messages. +/// @note Inspired and derived from the work done at: https://github.com/r45635/HVAC-IR-Control +/// @warning Consider this very alpha code. Seems to work, but not validated. +class IRMirageAc { + public: + explicit IRMirageAc(const uint16_t pin, const bool inverted = false, + const bool use_modulation = true); + void stateReset(void); +#if SEND_MIRAGE + void send(const uint16_t repeat = kMirageMinRepeat); + /// Run the calibration to calculate uSec timing offsets for this platform. + /// @return The uSec timing offset needed per modulation of the IR Led. + /// @note This will produce a 65ms IR signal pulse at 38kHz. + /// Only ever needs to be run once per object instantiation, if at all. + int8_t calibrate(void) { return _irsend.calibrate(); } +#endif // SEND_MIRAGE + void begin(void); + void on(void); + void off(void); + void setPower(const bool on); + bool getPower(void) const; + void setTemp(const uint8_t degrees); + uint8_t getTemp(void) const; + void setFan(const uint8_t speed); + uint8_t getFan(void) const; + void setMode(const uint8_t mode); + uint8_t getMode(void) const; + uint8_t* getRaw(void); + void setRaw(const uint8_t* data); + uint32_t getClock(void) const; + void setClock(const uint32_t nr_of_seconds); + void setTurbo(const bool on); + bool getTurbo(void) const; + void setLight(const bool on); + bool getLight(void) const; + void setSleep(const bool on); + bool getSleep(void) const; + void setSwingV(const uint8_t position); + uint8_t getSwingV(void) const; + void setSwingH(const bool on); + bool getSwingH(void) const; + void setQuiet(const bool on); + bool getQuiet(void) const; + void setCleanToggle(const bool on); + bool getCleanToggle(void) const; + void setFilter(const bool on); + bool getFilter(void) const; + void setIFeel(const bool on); + bool getIFeel(void) const; + void setSensorTemp(const uint8_t degrees); + uint16_t getSensorTemp(void) const; + uint16_t getOnTimer(void) const; + uint16_t getOffTimer(void) const; + void setOnTimer(const uint16_t nr_of_mins); + void setOffTimer(const uint16_t nr_of_mins); + mirage_ac_remote_model_t getModel(const bool useRaw = false) const; + void setModel(const mirage_ac_remote_model_t model); + static mirage_ac_remote_model_t getModel(const uint8_t *state); + static bool validChecksum(const uint8_t* data); + static uint8_t calculateChecksum(const uint8_t* data); + static uint8_t convertMode(const stdAc::opmode_t mode); + static uint8_t convertFan(const stdAc::fanspeed_t speed, + const mirage_ac_remote_model_t model = mirage_ac_remote_model_t::KKG9AC1); + static uint8_t convertSwingV(const stdAc::swingv_t position); + static stdAc::opmode_t toCommonMode(const uint8_t mode); + static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed, + const mirage_ac_remote_model_t model = mirage_ac_remote_model_t::KKG9AC1); + static stdAc::swingv_t toCommonSwingV(const uint8_t pos); + stdAc::state_t toCommon(void) const; + void fromCommon(const stdAc::state_t state); + String toString(void) const; +#ifndef UNIT_TEST + + private: + IRsend _irsend; ///< Instance of the IR send class +#else // UNIT_TEST + /// @cond IGNORE + IRsendTest _irsend; ///< Instance of the testing IR send class + /// @endcond +#endif // UNIT_TEST + Mirage120Protocol _; + mirage_ac_remote_model_t _model; + void checksum(void); +}; +#endif // IR_MIRAGE_H_ diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Mitsubishi.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Mitsubishi.cpp index 03e562ef5..160a882bf 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Mitsubishi.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Mitsubishi.cpp @@ -1166,7 +1166,7 @@ void IRsend::sendMitsubishi112(const unsigned char data[], } #endif // SEND_MITSUBISHI112 -#if DECODE_MITSUBISHI112 || DECODE_TCL112AC +#if (DECODE_MITSUBISHI112 || DECODE_TCL112AC) /// Decode the supplied Mitsubishi/TCL 112-bit A/C message. /// (MITSUBISHI112, TCL112AC) /// Status: STABLE / Reported as working. @@ -1212,7 +1212,7 @@ bool IRrecv::decodeMitsubishi112(decode_results *results, uint16_t offset, gap = kMitsubishi112Gap; } #endif // DECODE_MITSUBISHI112 -#if DECODE_TCL112AC +#if (DECODE_TCL112AC || DECODE_TEKNOPOINT) if (typeguess == decode_type_t::UNKNOWN && // We didn't match Mitsubishi112 matchMark(results->rawbuf[offset], kTcl112AcHdrMark, kTcl112AcHdrMarkTolerance, 0)) { @@ -1224,7 +1224,7 @@ bool IRrecv::decodeMitsubishi112(decode_results *results, uint16_t offset, gap = kTcl112AcGap; tolerance += kTcl112AcTolerance; } -#endif // DECODE_TCL112AC +#endif // (DECODE_TCL112AC || DECODE_TEKNOPOINT) if (typeguess == decode_type_t::UNKNOWN) return false; // No header matched. offset++; diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Rhoss.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Rhoss.cpp new file mode 100644 index 000000000..f906f49be --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Rhoss.cpp @@ -0,0 +1,364 @@ +// Copyright 2021 Tom Rosenback + +/// @file +/// @brief Support for Rhoss protocols. + +#include "ir_Rhoss.h" +#include +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRtext.h" +#include "IRutils.h" + +const uint16_t kRhossHdrMark = 3042; +const uint16_t kRhossHdrSpace = 4248; +const uint16_t kRhossBitMark = 648; +const uint16_t kRhossOneSpace = 1545; +const uint16_t kRhossZeroSpace = 457; +const uint32_t kRhossGap = kDefaultMessageGap; +const uint16_t kRhossFreq = 38; + +using irutils::addBoolToString; +using irutils::addModeToString; +using irutils::addFanToString; +using irutils::addTempToString; + +#if SEND_RHOSS +/// Send a Rhoss HVAC formatted message. +/// Status: STABLE / Reported as working. +/// @param[in] data The message to be sent. +/// @param[in] nbytes The number of bytes of message to be sent. +/// @param[in] repeat The number of times the command is to be repeated. +void IRsend::sendRhoss(const unsigned char data[], const uint16_t nbytes, + const uint16_t repeat) { + // Check if we have enough bytes to send a proper message. + if (nbytes < kRhossStateLength) return; + + // We always send a message, even for repeat=0, hence '<= repeat'. + for (uint16_t r = 0; r <= repeat; r++) { + sendGeneric(kRhossHdrMark, kRhossHdrSpace, kRhossBitMark, + kRhossOneSpace, kRhossBitMark, kRhossZeroSpace, + kRhossBitMark, kRhossZeroSpace, + data, nbytes, kRhossFreq, false, 0, kDutyDefault); + mark(kRhossBitMark); + // Gap + space(kRhossGap); + } +} +#endif // SEND_RHOSS + +#if DECODE_RHOSS +/// Decode the supplied Rhoss formatted message. +/// Status: STABLE / Known working. +/// @param[in,out] results Ptr to the data to decode & where to store the result +/// @param[in] offset The starting index to use when attempting to decode the +/// raw data. Typically/Defaults to kStartOffset. +/// @param[in] nbits The number of data bits to expect. +/// @param[in] strict Flag indicating if we should perform strict matching. +bool IRrecv::decodeRhoss(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (strict && nbits != kRhossBits) return false; + + if (results->rawlen <= 2 * nbits + kHeader + kFooter - 1 + offset) { + return false; // Can't possibly be a valid Rhoss message. + } + + uint16_t used; + // Header + Data Block (96 bits) + Footer + used = matchGeneric(results->rawbuf + offset, results->state, + results->rawlen - offset, kRhossBits, + kRhossHdrMark, kRhossHdrSpace, + kRhossBitMark, kRhossOneSpace, + kRhossBitMark, kRhossZeroSpace, + kRhossBitMark, kRhossZeroSpace, + false, kUseDefTol, kMarkExcess, false); + + if (!used) return false; + offset += used; + + // Footer (Part 2) + if (!matchMark(results->rawbuf[offset++], kRhossBitMark)) { + return false; + } + + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kRhossGap)) { + return false; + } + + if (strict && !IRRhossAc::validChecksum(results->state)) return false; + + // Success + results->decode_type = decode_type_t::RHOSS; + results->bits = nbits; + // No need to record the state as we stored it as we decoded it. + // As we use result->state, we don't record value, address, or command as it + // is a union data type. + return true; +} + +#endif // DECODE_RHOSS + +/// Class constructor +/// @param[in] pin GPIO to be used when sending. +/// @param[in] inverted Is the output signal to be inverted? +/// @param[in] use_modulation Is frequency modulation to be used? +IRRhossAc::IRRhossAc(const uint16_t pin, const bool inverted, + const bool use_modulation) + : _irsend(pin, inverted, use_modulation) { this->stateReset(); } + +/// Set up hardware to be able to send a message. +void IRRhossAc::begin(void) { _irsend.begin(); } + +#if SEND_RHOSS +/// Send the current internal state as an IR message. +/// @param[in] repeat Nr. of times the message will be repeated. +void IRRhossAc::send(const uint16_t repeat) { + _irsend.sendRhoss(getRaw(), kRhossStateLength, repeat); +} +#endif // SEND_RHOSS + +/// Calculate the checksum for the supplied state. +/// @param[in] state The source state to generate the checksum from. +/// @param[in] length Length of the supplied state to checksum. +/// @return The checksum value. +uint8_t IRRhossAc::calcChecksum(const uint8_t state[], const uint16_t length) { + return sumBytes(state, length - 1); +} + +/// Verify the checksum is valid for a given state. +/// @param[in] state The array to verify the checksum of. +/// @param[in] length The size of the state. +/// @return A boolean indicating if it's checksum is valid. +bool IRRhossAc::validChecksum(const uint8_t state[], const uint16_t length) { + return (state[length - 1] == IRRhossAc::calcChecksum(state, length)); +} + +/// Update the checksum value for the internal state. +void IRRhossAc::checksum(void) { + _.Sum = IRRhossAc::calcChecksum(_.raw, kRhossStateLength); + _.raw[kRhossStateLength - 1] = _.Sum; +} + +/// Reset the internals of the object to a known good state. +void IRRhossAc::stateReset(void) { + for (uint8_t i = 1; i < kRhossStateLength; i++) _.raw[i] = 0x0; + _.raw[0] = 0xAA; + _.raw[2] = 0x60; + _.raw[6] = 0x54; + _.Power = kRhossDefaultPower; + _.Fan = kRhossDefaultFan; + _.Mode = kRhossDefaultMode; + _.Swing = kRhossDefaultSwing; + _.Temp = kRhossDefaultTemp - kRhossTempMin; +} + +/// Get the raw state of the object, suitable to be sent with the appropriate +/// IRsend object method. +/// @return A PTR to the internal state. +uint8_t* IRRhossAc::getRaw(void) { + checksum(); // Ensure correct bit array before returning + return _.raw; +} + +/// Set the raw state of the object. +/// @param[state] state The raw state from the native IR message. +void IRRhossAc::setRaw(const uint8_t state[]) { + std::memcpy(_.raw, state, kRhossStateLength); +} + +/// Set the internal state to have the power on. +void IRRhossAc::on(void) { setPower(true); } + +/// Set the internal state to have the power off. +void IRRhossAc::off(void) { setPower(false); } + +/// Set the internal state to have the desired power. +/// @param[in] on The desired power state. +void IRRhossAc::setPower(const bool on) { + _.Power = (on ? kRhossPowerOn : kRhossPowerOff); +} + +/// Get the power setting from the internal state. +/// @return A boolean indicating the power setting. +bool IRRhossAc::getPower(void) const { + return _.Power == kRhossPowerOn; +} + +/// Set the temperature. +/// @param[in] degrees The temperature in degrees celsius. +void IRRhossAc::setTemp(const uint8_t degrees) { + uint8_t temp = std::max(kRhossTempMin, degrees); + _.Temp = std::min(kRhossTempMax, temp) - kRhossTempMin; +} + +/// Get the current temperature setting. +/// @return Get current setting for temp. in degrees celsius. +uint8_t IRRhossAc::getTemp(void) const { + return _.Temp + kRhossTempMin; +} + +/// Set the speed of the fan. +/// @param[in] speed The desired setting. +void IRRhossAc::setFan(const uint8_t speed) { + switch (speed) { + case kRhossFanAuto: + case kRhossFanMin: + case kRhossFanMed: + case kRhossFanMax: + _.Fan = speed; + break; + default: + _.Fan = kRhossFanAuto; + } +} + +/// Get the current fan speed setting. +/// @return The current fan speed. +uint8_t IRRhossAc::getFan(void) const { + return _.Fan; +} + +/// Set the Vertical Swing mode of the A/C. +/// @param[in] state true, the Swing is on. false, the Swing is off. +void IRRhossAc::setSwing(const bool state) { + _.Swing = state; +} + +/// Get the Vertical Swing speed of the A/C. +/// @return The native swing speed setting. +uint8_t IRRhossAc::getSwing(void) const { + return _.Swing; +} + +/// Get the current operation mode setting. +/// @return The current operation mode. +uint8_t IRRhossAc::getMode(void) const { + return _.Mode; +} + +/// Set the desired operation mode. +/// @param[in] mode The desired operation mode. +void IRRhossAc::setMode(const uint8_t mode) { + switch (mode) { + case kRhossModeFan: + case kRhossModeCool: + case kRhossModeDry: + case kRhossModeHeat: + case kRhossModeAuto: + _.Mode = mode; + return; + default: + _.Mode = kRhossDefaultMode; + break; + } +} + +/// Convert a stdAc::opmode_t enum into its native mode. +/// @param[in] mode The enum to be converted. +/// @return The native equivalent of the enum. +uint8_t IRRhossAc::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: + return kRhossModeCool; + case stdAc::opmode_t::kHeat: + return kRhossModeHeat; + case stdAc::opmode_t::kDry: + return kRhossModeDry; + case stdAc::opmode_t::kFan: + return kRhossModeFan; + case stdAc::opmode_t::kAuto: + return kRhossModeAuto; + default: + return kRhossDefaultMode; + } +} + +/// Convert a stdAc::fanspeed_t enum into it's native speed. +/// @param[in] speed The enum to be converted. +/// @return The native equivalent of the enum. +uint8_t IRRhossAc::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: + case stdAc::fanspeed_t::kLow: + return kRhossFanMin; + case stdAc::fanspeed_t::kMedium: + return kRhossFanMed; + case stdAc::fanspeed_t::kHigh: + case stdAc::fanspeed_t::kMax: + return kRhossFanMax; + default: + return kRhossDefaultFan; + } +} + +/// Convert a native mode into its stdAc equivalent. +/// @param[in] mode The native setting to be converted. +/// @return The stdAc equivalent of the native setting. +stdAc::opmode_t IRRhossAc::toCommonMode(const uint8_t mode) { + switch (mode) { + case kRhossModeCool: return stdAc::opmode_t::kCool; + case kRhossModeHeat: return stdAc::opmode_t::kHeat; + case kRhossModeDry: return stdAc::opmode_t::kDry; + case kRhossModeFan: return stdAc::opmode_t::kFan; + case kRhossModeAuto: return stdAc::opmode_t::kAuto; + default: return stdAc::opmode_t::kAuto; + } +} + +/// Convert a native fan speed into its stdAc equivalent. +/// @param[in] speed The native setting to be converted. +/// @return The stdAc equivalent of the native setting. +stdAc::fanspeed_t IRRhossAc::toCommonFanSpeed(const uint8_t speed) { + switch (speed) { + case kRhossFanMax: return stdAc::fanspeed_t::kMax; + case kRhossFanMed: return stdAc::fanspeed_t::kMedium; + case kRhossFanMin: return stdAc::fanspeed_t::kMin; + case kRhossFanAuto: + default: + return stdAc::fanspeed_t::kAuto; + } +} + +/// Convert the current internal state into its stdAc::state_t equivalent. +/// @return The stdAc equivalent of the native settings. +stdAc::state_t IRRhossAc::toCommon(void) const { + stdAc::state_t result; + result.protocol = decode_type_t::RHOSS; + result.power = getPower(); + result.mode = toCommonMode(_.Mode); + result.celsius = true; + result.degrees = _.Temp; + result.fanspeed = toCommonFanSpeed(_.Fan); + result.swingv = _.Swing ? stdAc::swingv_t::kAuto : stdAc::swingv_t::kOff; + // Not supported. + result.model = -1; + result.turbo = false; + result.swingh = stdAc::swingh_t::kOff; + result.light = false; + result.filter = false; + result.econo = false; + result.quiet = false; + result.clean = false; + result.beep = false; + result.sleep = -1; + result.clock = -1; + return result; +} + +/// Convert the current internal state into a human readable string. +/// @return A human readable string. +String IRRhossAc::toString(void) const { + String result = ""; + result.reserve(70); // Reserve some heap for the string to reduce fragging. + result += addBoolToString(getPower(), kPowerStr, false); + result += addModeToString(getMode(), kRhossModeAuto, kRhossModeCool, + kRhossModeHeat, kRhossModeDry, kRhossModeFan); + result += addTempToString(getTemp()); + result += addFanToString(getFan(), kRhossFanMax, kRhossFanMin, + kRhossFanAuto, kRhossFanAuto, + kRhossFanMed); + result += addBoolToString(getSwing(), kSwingVStr); + return result; +} diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Rhoss.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Rhoss.h new file mode 100644 index 000000000..8f66ce738 --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Rhoss.h @@ -0,0 +1,145 @@ +// Copyright 2021 Tom Rosenback + +/// @file +/// @brief Support for Rhoss A/C protocol +// Supports: +// Brand: Rhoss, Model: Idrowall MPCV 20-30-35-40 + +#ifndef IR_RHOSS_H_ +#define IR_RHOSS_H_ + +#define __STDC_LIMIT_MACROS +#include +#ifndef UNIT_TEST +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" +#ifdef UNIT_TEST +#include "IRsend_test.h" +#endif + + +/// Native representation of a Rhoss A/C message. +union RhossProtocol{ + uint8_t raw[kRhossStateLength]; // The state of the IR remote. + struct { + // Byte 0 + uint8_t :8; // Typically 0xAA + // Byte 1 + uint8_t Temp :4; + uint8_t :4; // Typically 0x0 + // Byte 2 + uint8_t :8; // Typically 0x60 + // Byte 3 + uint8_t :8; // Typically 0x0 + // Byte 4 + uint8_t Fan :2; + uint8_t :2; // Typically 0x0 + uint8_t Mode :4; + // Byte 5 + uint8_t Swing :1; + uint8_t :5; // Typically 0x0 + uint8_t Power :2; + // Byte 6 + uint8_t :8; // Typically 0x54 + // Byte 7 + uint8_t :8; // Typically 0x0 + // Byte 8 + uint8_t :8; // Typically 0x0 + // Byte 9 + uint8_t :8; // Typically 0x0 + // Byte 10 + uint8_t :8; // Typically 0x0 + // Byte 11 + uint8_t Sum :8; + }; +}; + +// Constants + +// Fan Control +const uint8_t kRhossFanAuto = 0b00; +const uint8_t kRhossFanMin = 0b01; +const uint8_t kRhossFanMed = 0b10; +const uint8_t kRhossFanMax = 0b11; +// Modes +const uint8_t kRhossModeHeat = 0b0001; +const uint8_t kRhossModeCool = 0b0010; +const uint8_t kRhossModeDry = 0b0011; +const uint8_t kRhossModeFan = 0b0100; +const uint8_t kRhossModeAuto = 0b0101; + +// Temperature +const uint8_t kRhossTempMin = 16; // Celsius +const uint8_t kRhossTempMax = 30; // Celsius + +// Power +const uint8_t kRhossPowerOn = 0b10; // 0x2 +const uint8_t kRhossPowerOff = 0b01; // 0x1 + +// Swing +const uint8_t kRhossSwingOn = 0b1; // 0x1 +const uint8_t kRhossSwingOff = 0b0; // 0x0 + +const uint8_t kRhossDefaultFan = kRhossFanAuto; +const uint8_t kRhossDefaultMode = kRhossModeCool; +const uint8_t kRhossDefaultTemp = 21; // Celsius +const bool kRhossDefaultPower = false; +const bool kRhossDefaultSwing = false; + +// Classes + +/// Class for handling detailed Rhoss A/C messages. +class IRRhossAc { + public: + explicit IRRhossAc(const uint16_t pin, const bool inverted = false, + const bool use_modulation = true); + + void stateReset(); +#if SEND_RHOSS + void send(const uint16_t repeat = kRhossDefaultRepeat); + /// Run the calibration to calculate uSec timing offsets for this platform. + /// @return The uSec timing offset needed per modulation of the IR Led. + /// @note This will produce a 65ms IR signal pulse at 38kHz. + /// Only ever needs to be run once per object instantiation, if at all. + int8_t calibrate(void) { return _irsend.calibrate(); } +#endif // SEND_RHOSS + void begin(); + static uint8_t calcChecksum(const uint8_t state[], + const uint16_t length = kRhossStateLength); + static bool validChecksum(const uint8_t state[], + const uint16_t length = kRhossStateLength); + void setPower(const bool state); + bool getPower(void) const; + void on(void); + void off(void); + void setTemp(const uint8_t temp); + uint8_t getTemp(void) const; + void setFan(const uint8_t speed); + uint8_t getFan(void) const; + void setSwing(const bool state); + uint8_t getSwing(void) const; + void setMode(const uint8_t mode); + uint8_t getMode(void) const; + uint8_t* getRaw(void); + void setRaw(const uint8_t state[]); + static uint8_t convertMode(const stdAc::opmode_t mode); + static uint8_t convertFan(const stdAc::fanspeed_t speed); + static stdAc::opmode_t toCommonMode(const uint8_t mode); + static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed); + stdAc::state_t toCommon(void) const; + String toString(void) const; +#ifndef UNIT_TEST + + private: + IRsend _irsend; +#else + /// @cond IGNORE + IRsendTest _irsend; + /// @endcond +#endif + RhossProtocol _; + void checksum(void); +}; +#endif // IR_RHOSS_H_ diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Samsung.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Samsung.cpp index 9e1ad4669..94cb52bba 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Samsung.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Samsung.cpp @@ -1,5 +1,5 @@ // Copyright 2009 Ken Shirriff -// Copyright 2017, 2018, 2019 David Conran +// Copyright 2017-2021 David Conran /// @file /// @brief Support for Samsung protocols. /// Samsung originally added from https://github.com/shirriff/Arduino-IRremote/ @@ -62,12 +62,25 @@ const uint16_t kSamsung36BitMark = 512; /// < uSeconds const uint16_t kSamsung36OneSpace = 1468; /// < uSeconds const uint16_t kSamsung36ZeroSpace = 490; /// < uSeconds +// _.Swing +const uint8_t kSamsungAcSwingV = 0b010; +const uint8_t kSamsungAcSwingH = 0b011; +const uint8_t kSamsungAcSwingBoth = 0b100; +const uint8_t kSamsungAcSwingOff = 0b111; +// _.FanSpecial +const uint8_t kSamsungAcFanSpecialOff = 0b000; +const uint8_t kSamsungAcPowerfulOn = 0b011; +const uint8_t kSamsungAcBreezeOn = 0b101; +const uint8_t kSamsungAcEconoOn = 0b111; + using irutils::addBoolToString; using irutils::addFanToString; using irutils::addIntToString; using irutils::addLabeledString; using irutils::addModeToString; using irutils::addTempToString; +using irutils::addToggleToString; +using irutils::minsToString; #if SEND_SAMSUNG /// Send a 32-bit Samsung formatted message. @@ -275,17 +288,22 @@ IRSamsungAc::IRSamsungAc(const uint16_t pin, const bool inverted, } /// Reset the internal state of the emulation. -/// @param[in] forcepower A flag indicating if force sending a special power +/// @param[in] extended A flag indicating if force sending a special extended /// message with the first `send()` call. /// @param[in] initialPower Set the initial power state. True, on. False, off. -void IRSamsungAc::stateReset(const bool forcepower, const bool initialPower) { +void IRSamsungAc::stateReset(const bool extended, const bool initialPower) { static const uint8_t kReset[kSamsungAcExtendedStateLength] = { 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, 0x01, 0x02, 0xAE, 0x71, 0x00, 0x15, 0xF0}; std::memcpy(_.raw, kReset, kSamsungAcExtendedStateLength); - _forcepower = forcepower; + _forceextended = extended; _lastsentpowerstate = initialPower; setPower(initialPower); + _OnTimerEnable = false; + _OffTimerEnable = false; + _Sleep = false; + _lastSleep = false; + _OnTimer = _OffTimer = _lastOnTimer = _lastOffTimer = 0; } /// Set up hardware to be able to send a message. @@ -351,30 +369,28 @@ void IRSamsungAc::checksum(void) { #if SEND_SAMSUNG_AC /// Send the current internal state as an IR message. /// @param[in] repeat Nr. of times the message will be repeated. -/// @param[in] calcchecksum Do we update the checksum before sending? /// @note Use for most function/mode/settings changes to the unit. /// i.e. When the device is already running. -void IRSamsungAc::send(const uint16_t repeat, const bool calcchecksum) { - // Do we need to send a the special power on/off message? i.e. An Extended Msg - if (getPower() != _lastsentpowerstate || _forcepower) { // We do. - sendExtended(repeat, calcchecksum); - _forcepower = false; // It has now been sent, so clear the flag if set. - } else { // No, it's just a normal message. - if (calcchecksum) checksum(); - _irsend.sendSamsungAC(_.raw, kSamsungAcStateLength, repeat); - } +void IRSamsungAc::send(const uint16_t repeat) { + // Do we need to send a special (extended) message? + if (getPower() != _lastsentpowerstate || _forceextended || + (_lastOnTimer != _OnTimer) || (_lastOffTimer != _OffTimer) || + (_Sleep != _lastSleep)) // We do. + sendExtended(repeat); + else // No, it's just a normal message. + _irsend.sendSamsungAC(getRaw(), kSamsungAcStateLength, repeat); } /// Send the extended current internal state as an IR message. /// @param[in] repeat Nr. of times the message will be repeated. -/// @param[in] calcchecksum Do we update the checksum before sending? -/// @note Use this for when you need to power on/off the device. -/// Samsung A/C requires an extended length message when you want to -/// change the power operating mode of the A/C unit. -void IRSamsungAc::sendExtended(const uint16_t repeat, const bool calcchecksum) { +/// @note Samsung A/C requires an extended length message when you want to +/// change the power operating mode, Timers, or Sleep setting of the A/C unit. +void IRSamsungAc::sendExtended(const uint16_t repeat) { + _lastsentpowerstate = getPower(); // Remember the last power state sent. + _lastOnTimer = _OnTimer; + _lastOffTimer = _OffTimer; static const uint8_t extended_middle_section[kSamsungAcSectionLength] = { 0x01, 0xD2, 0x0F, 0x00, 0x00, 0x00, 0x00}; - if (calcchecksum) checksum(); // Copy/convert the internal state to an extended state by // copying the second section to the third section, and inserting the extended // middle (second) section. @@ -383,13 +399,16 @@ void IRSamsungAc::sendExtended(const uint16_t repeat, const bool calcchecksum) { kSamsungAcSectionLength); std::memcpy(_.raw + kSamsungAcSectionLength, extended_middle_section, kSamsungAcSectionLength); + _setOnTimer(); + _setSleepTimer(); // This also sets any Off Timer if needed too. // Send it. - _irsend.sendSamsungAC(_.raw, kSamsungAcExtendedStateLength, repeat); + _irsend.sendSamsungAC(getRaw(), kSamsungAcExtendedStateLength, repeat); // Now revert it by copying the third section over the second section. std::memcpy(_.raw + kSamsungAcSectionLength, - _.raw + 2* kSamsungAcSectionLength, + _.raw + 2 * kSamsungAcSectionLength, kSamsungAcSectionLength); - _lastsentpowerstate = getPower(); // Remember the last power state sent. + + _forceextended = false; // It has now been sent, so clear the flag if set. } /// Send the special extended "On" message as the library can't seem to @@ -434,6 +453,11 @@ void IRSamsungAc::setRaw(const uint8_t new_code[], const uint16_t length) { kSamsungAcExtendedStateLength)); // Shrink the extended state into a normal state. if (length > kSamsungAcStateLength) { + _OnTimerEnable = _.OnTimerEnable; + _OffTimerEnable = _.OffTimerEnable; + _Sleep = _.Sleep5 && _.Sleep12; + _OnTimer = _getOnTimer(); + _OffTimer = _getOffTimer(); for (uint8_t i = kSamsungAcStateLength; i < length; i++) _.raw[i - kSamsungAcSectionLength] = _.raw[i]; } @@ -448,14 +472,13 @@ void IRSamsungAc::off(void) { setPower(false); } /// Change the power setting. /// @param[in] on true, the setting is on. false, the setting is off. void IRSamsungAc::setPower(const bool on) { - _.Power1 = !on; // Cleared when on. - _.Power6 = (on ? 0b11 : 0b00); + _.Power1 = _.Power2 = (on ? 0b11 : 0b00); } /// Get the value of the current power setting. /// @return true, the setting is on. false, the setting is off. bool IRSamsungAc::getPower(void) const { - return (_.Power6 == 0b11) && !_.Power1; + return _.Power1 == 0b11 && _.Power2 == 0b11; } /// Set the temperature. @@ -524,56 +547,79 @@ uint8_t IRSamsungAc::getFan(void) const { /// Get the vertical swing setting of the A/C. /// @return true, the setting is on. false, the setting is off. -/// @todo (Hollako) Explain why sometimes the LSB of remote_state[9] is a 1. -/// e.g. 0xAE or 0XAF for swing move. bool IRSamsungAc::getSwing(void) const { - return _.Swing == kSamsungAcSwingMove; + switch (_.Swing) { + case kSamsungAcSwingV: + case kSamsungAcSwingBoth: return true; + default: return false; + } } /// Set the vertical swing setting of the A/C. /// @param[in] on true, the setting is on. false, the setting is off. -/// @todo (Hollako) Explain why sometimes the LSB of remote_state[9] is a 1. -/// e.g. 0xAE or 0XAF for swing move. void IRSamsungAc::setSwing(const bool on) { - _.Swing = (on ? kSamsungAcSwingMove : kSamsungAcSwingStop); + switch (_.Swing) { + case kSamsungAcSwingBoth: + case kSamsungAcSwingH: + _.Swing = on ? kSamsungAcSwingBoth : kSamsungAcSwingH; + break; + default: + _.Swing = on ? kSamsungAcSwingV : kSamsungAcSwingOff; + } } -/// Get the Beep setting of the A/C. +/// Get the horizontal swing setting of the A/C. /// @return true, the setting is on. false, the setting is off. -bool IRSamsungAc::getBeep(void) const { - return _.Beep; +bool IRSamsungAc::getSwingH(void) const { + switch (_.Swing) { + case kSamsungAcSwingH: + case kSamsungAcSwingBoth: return true; + default: return false; + } } -/// Set the Beep setting of the A/C. +/// Set the horizontal swing setting of the A/C. /// @param[in] on true, the setting is on. false, the setting is off. -void IRSamsungAc::setBeep(const bool on) { - _.Beep = on; +void IRSamsungAc::setSwingH(const bool on) { + switch (_.Swing) { + case kSamsungAcSwingV: + case kSamsungAcSwingBoth: + _.Swing = on ? kSamsungAcSwingBoth : kSamsungAcSwingV; + break; + default: + _.Swing = on ? kSamsungAcSwingH : kSamsungAcSwingOff; + } } -/// Get the Clean setting of the A/C. +/// Get the Beep toggle setting of the A/C. +/// @return true, the setting is on. false, the setting is off. +bool IRSamsungAc::getBeep(void) const { return _.BeepToggle; } + +/// Set the Beep toggle setting of the A/C. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRSamsungAc::setBeep(const bool on) { _.BeepToggle = on; } + +/// Get the Clean toggle setting of the A/C. /// @return true, the setting is on. false, the setting is off. bool IRSamsungAc::getClean(void) const { - return _.Clean10 && _.Clean11; + return _.CleanToggle10 && _.CleanToggle11; } -/// Set the Clean setting of the A/C. +/// Set the Clean toggle setting of the A/C. /// @param[in] on true, the setting is on. false, the setting is off. void IRSamsungAc::setClean(const bool on) { - _.Clean10 = on; - _.Clean11 = on; + _.CleanToggle10 = on; + _.CleanToggle11 = on; } /// Get the Quiet setting of the A/C. /// @return true, the setting is on. false, the setting is off. -bool IRSamsungAc::getQuiet(void) const { - return !_.Quiet1 && _.Quiet5; -} +bool IRSamsungAc::getQuiet(void) const { return _.Quiet; } /// Set the Quiet setting of the A/C. /// @param[in] on true, the setting is on. false, the setting is off. void IRSamsungAc::setQuiet(const bool on) { - _.Quiet1 = !on; // Cleared when on. - _.Quiet5 = on; + _.Quiet = on; if (on) { // Quiet mode seems to set fan speed to auto. setFan(kSamsungAcFanAuto); @@ -584,25 +630,20 @@ void IRSamsungAc::setQuiet(const bool on) { /// Get the Powerful (Turbo) setting of the A/C. /// @return true, the setting is on. false, the setting is off. bool IRSamsungAc::getPowerful(void) const { - return !(_.Powerful8 & kSamsungAcPowerfulMask8) && - (_.Powerful10 == kSamsungAcPowerful10On) && + return (_.FanSpecial == kSamsungAcPowerfulOn) && (_.Fan == kSamsungAcFanTurbo); } /// Set the Powerful (Turbo) setting of the A/C. /// @param[in] on true, the setting is on. false, the setting is off. void IRSamsungAc::setPowerful(const bool on) { - uint8_t off_value = getBreeze() ? kSamsungAcBreezeOn : 0b000; - _.Powerful10 = (on ? kSamsungAcPowerful10On : off_value); + uint8_t off_value = (getBreeze() || getEcono()) ? _.FanSpecial + : kSamsungAcFanSpecialOff; + _.FanSpecial = (on ? kSamsungAcPowerfulOn : off_value); if (on) { - _.Powerful8 &= ~kSamsungAcPowerfulMask8; // Bit needs to be cleared. // Powerful mode sets fan speed to Turbo. setFan(kSamsungAcFanTurbo); setQuiet(false); // Powerful 'on' is mutually exclusive to Quiet. - } else { - _.Powerful8 |= kSamsungAcPowerfulMask8; // Bit needs to be set. - // Turning off Powerful mode sets fan speed to Auto if we were in Turbo mode - if (_.Fan == kSamsungAcFanTurbo) setFan(kSamsungAcFanAuto); } } @@ -610,7 +651,7 @@ void IRSamsungAc::setPowerful(const bool on) { /// @return true, the setting is on. false, the setting is off. /// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1062 bool IRSamsungAc::getBreeze(void) const { - return (_.Breeze == kSamsungAcBreezeOn) && + return (_.FanSpecial == kSamsungAcBreezeOn) && (_.Fan == kSamsungAcFanAuto && !getSwing()); } @@ -618,36 +659,155 @@ bool IRSamsungAc::getBreeze(void) const { /// @param[in] on true, the setting is on. false, the setting is off. /// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1062 void IRSamsungAc::setBreeze(const bool on) { - uint8_t off_value = getPowerful() ? kSamsungAcPowerful10On : 0b000; - _.Breeze = (on ? kSamsungAcBreezeOn : off_value); + const uint8_t off_value = (getPowerful() || + getEcono()) ? _.FanSpecial + : kSamsungAcFanSpecialOff; + _.FanSpecial = (on ? kSamsungAcBreezeOn : off_value); if (on) { setFan(kSamsungAcFanAuto); setSwing(false); } } +/// Get the current Economy (Eco) setting of the A/C. +/// @return true, the setting is on. false, the setting is off. +bool IRSamsungAc::getEcono(void) const { + return (_.FanSpecial == kSamsungAcEconoOn) && + (_.Fan == kSamsungAcFanAuto && getSwing()); +} + +/// Set the current Economy (Eco) setting of the A/C. +/// @param[in] on true, the setting is on. false, the setting is off. +void IRSamsungAc::setEcono(const bool on) { + const uint8_t off_value = (getBreeze() || + getPowerful()) ? _.FanSpecial + : kSamsungAcFanSpecialOff; + _.FanSpecial = (on ? kSamsungAcEconoOn : off_value); + if (on) { + setFan(kSamsungAcFanAuto); + setSwing(true); + } +} + /// Get the Display (Light/LED) setting of the A/C. /// @return true, the setting is on. false, the setting is off. -bool IRSamsungAc::getDisplay(void) const { - return _.Display; -} +bool IRSamsungAc::getDisplay(void) const { return _.Display; } /// Set the Display (Light/LED) setting of the A/C. /// @param[in] on true, the setting is on. false, the setting is off. -void IRSamsungAc::setDisplay(const bool on) { - _.Display = on; -} +void IRSamsungAc::setDisplay(const bool on) { _.Display = on; } /// Get the Ion (Filter) setting of the A/C. /// @return true, the setting is on. false, the setting is off. -bool IRSamsungAc::getIon(void) const { - return _.Ion; -} +bool IRSamsungAc::getIon(void) const { return _.Ion; } /// Set the Ion (Filter) setting of the A/C. /// @param[in] on true, the setting is on. false, the setting is off. -void IRSamsungAc::setIon(const bool on) { - _.Ion = on; +void IRSamsungAc::setIon(const bool on) { _.Ion = on; } + +/// Get the On Timer setting of the A/C from a raw extended state. +/// @return The Nr. of minutes the On Timer is set for. +uint16_t IRSamsungAc::_getOnTimer(void) const { + if (_.OnTimeDay) return 24 * 60; + return (_.OnTimeHrs2 * 2 + _.OnTimeHrs1) * 60 + _.OnTimeMins * 10; +} + +/// Set the current On Timer value of the A/C into the raw extended state. +void IRSamsungAc::_setOnTimer(void) { + _.OnTimerEnable = _OnTimerEnable = (_OnTimer > 0); + _.OnTimeDay = (_OnTimer >= 24 * 60); + if (_.OnTimeDay) { + _.OnTimeHrs2 = _.OnTimeHrs1 = _.OnTimeMins = 0; + return; + } + _.OnTimeMins = (_OnTimer % 60) / 10; + const uint8_t hours = _OnTimer / 60; + _.OnTimeHrs1 = hours & 0b1; + _.OnTimeHrs2 = hours >> 1; +} + +/// Get the Off Timer setting of the A/C from a raw extended state. +/// @return The Nr. of minutes the Off Timer is set for. +uint16_t IRSamsungAc::_getOffTimer(void) const { + if (_.OffTimeDay) return 24 * 60; + return (_.OffTimeHrs2 * 2 + _.OffTimeHrs1) * 60 + _.OffTimeMins * 10; +} + +/// Set the current Off Timer value of the A/C into the raw extended state. +void IRSamsungAc::_setOffTimer(void) { + _.OffTimerEnable = _OffTimerEnable = (_OffTimer > 0); + _.OffTimeDay = (_OffTimer >= 24 * 60); + if (_.OffTimeDay) { + _.OffTimeHrs2 = _.OffTimeHrs1 = _.OffTimeMins = 0; + return; + } + _.OffTimeMins = (_OffTimer % 60) / 10; + const uint8_t hours = _OffTimer / 60; + _.OffTimeHrs1 = hours & 0b1; + _.OffTimeHrs2 = hours >> 1; +} + +// Set the current Sleep Timer value of the A/C into the raw extended state. +void IRSamsungAc::_setSleepTimer(void) { + _setOffTimer(); + // The Sleep mode/timer should only be engaged if an off time has been set. + _.Sleep5 = _Sleep && _OffTimerEnable; + _.Sleep12 = _.Sleep5; +} + +/// Get the On Timer setting of the A/C. +/// @return The Nr. of minutes the On Timer is set for. +uint16_t IRSamsungAc::getOnTimer(void) const { return _OnTimer; } + +/// Get the Off Timer setting of the A/C. +/// @return The Nr. of minutes the Off Timer is set for. +/// @note Sleep & Off Timer share the same timer. +uint16_t IRSamsungAc::getOffTimer(void) const { + return _Sleep ? 0 : _OffTimer; +} + +/// Get the Sleep Timer setting of the A/C. +/// @return The Nr. of minutes the Off Timer is set for. +/// @note Sleep & Off Timer share the same timer. +uint16_t IRSamsungAc::getSleepTimer(void) const { + return _Sleep ? _OffTimer : 0; +} + +#define TIMER_RESOLUTION(mins) \ + (((std::min((mins), (uint16_t)(24 * 60))) / 10) * 10) + +/// Set the On Timer value of the A/C. +/// @param[in] nr_of_mins The number of minutes the timer should be. +/// @note The timer time only has a resolution of 10 mins. +/// @note Setting the On Timer active will cancel the Sleep timer/setting. +void IRSamsungAc::setOnTimer(const uint16_t nr_of_mins) { + // Limit to one day, and round down to nearest 10 min increment. + _OnTimer = TIMER_RESOLUTION(nr_of_mins); + _OnTimerEnable = _OnTimer > 0; + if (_OnTimer) _Sleep = false; +} + +/// Set the Off Timer value of the A/C. +/// @param[in] nr_of_mins The number of minutes the timer should be. +/// @note The timer time only has a resolution of 10 mins. +/// @note Setting the Off Timer active will cancel the Sleep timer/setting. +void IRSamsungAc::setOffTimer(const uint16_t nr_of_mins) { + // Limit to one day, and round down to nearest 10 min increment. + _OffTimer = TIMER_RESOLUTION(nr_of_mins); + _OffTimerEnable = _OffTimer > 0; + if (_OffTimer) _Sleep = false; +} + +/// Set the Sleep Timer value of the A/C. +/// @param[in] nr_of_mins The number of minutes the timer should be. +/// @note The timer time only has a resolution of 10 mins. +/// @note Sleep timer acts as an Off timer, and cancels any On Timer. +void IRSamsungAc::setSleepTimer(const uint16_t nr_of_mins) { + // Limit to one day, and round down to nearest 10 min increment. + _OffTimer = TIMER_RESOLUTION(nr_of_mins); + if (_OffTimer) setOnTimer(0); // Clear the on timer if set. + _Sleep = _OffTimer > 0; + _OffTimerEnable = _Sleep; } /// Convert a stdAc::opmode_t enum into its native mode. @@ -714,18 +874,17 @@ stdAc::state_t IRSamsungAc::toCommon(void) const { result.celsius = true; result.degrees = getTemp(); result.fanspeed = toCommonFanSpeed(_.Fan); - result.swingv = getSwing() ? stdAc::swingv_t::kAuto : - stdAc::swingv_t::kOff; + result.swingv = getSwing() ? stdAc::swingv_t::kAuto : stdAc::swingv_t::kOff; + result.swingh = getSwingH() ? stdAc::swingh_t::kAuto : stdAc::swingh_t::kOff; result.quiet = getQuiet(); result.turbo = getPowerful(); + result.econo = getEcono(); result.clean = getClean(); - result.beep = _.Beep; + result.beep = _.BeepToggle; result.light = _.Display; result.filter = _.Ion; + result.sleep = _Sleep ? getSleepTimer() : -1; // Not supported. - result.swingh = stdAc::swingh_t::kOff; - result.econo = false; - result.sleep = -1; result.clock = -1; return result; } @@ -734,7 +893,7 @@ stdAc::state_t IRSamsungAc::toCommon(void) const { /// @return A human readable string. String IRSamsungAc::toString(void) const { String result = ""; - result.reserve(115); // Reserve some heap for the string to reduce fragging. + result.reserve(230); // Reserve some heap for the string to reduce fragging. result += addBoolToString(getPower(), kPowerStr, false); result += addModeToString(_.Mode, kSamsungAcAuto, kSamsungAcCool, kSamsungAcHeat, kSamsungAcDry, @@ -764,14 +923,21 @@ String IRSamsungAc::toString(void) const { break; } result += ')'; - result += addBoolToString(getSwing(), kSwingStr); - result += addBoolToString(_.Beep, kBeepStr); - result += addBoolToString(getClean(), kCleanStr); + result += addBoolToString(getSwing(), kSwingVStr); + result += addBoolToString(getSwingH(), kSwingHStr); + result += addToggleToString(_.BeepToggle, kBeepStr); + result += addToggleToString(getClean(), kCleanStr); result += addBoolToString(getQuiet(), kQuietStr); result += addBoolToString(getPowerful(), kPowerfulStr); + result += addBoolToString(getEcono(), kEconoStr); result += addBoolToString(getBreeze(), kBreezeStr); result += addBoolToString(_.Display, kLightStr); result += addBoolToString(_.Ion, kIonStr); + if (_OnTimerEnable) + result += addLabeledString(minsToString(_OnTimer), kOnTimerStr); + if (_OffTimerEnable) + result += addLabeledString(minsToString(_OffTimer), + _Sleep ? kSleepTimerStr : kOffTimerStr); return result; } @@ -811,9 +977,6 @@ bool IRrecv::decodeSamsungAC(decode_results *results, uint16_t offset, offset += used; } // Compliance - // Is the signature correct? - DPRINTLN("DEBUG: Checking signature."); - if (results->state[0] != 0x02 || results->state[2] != 0x0F) return false; if (strict) { // Is the checksum valid? if (!IRSamsungAc::validChecksum(results->state, nbits / 8)) { diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Samsung.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Samsung.h index bf9215edc..acabb3648 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Samsung.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Samsung.h @@ -1,4 +1,4 @@ -// Copyright 2018 David Conran +// Copyright 2018-2021 David Conran /// @file /// @brief Support for Samsung protocols. /// Samsung originally added from https://github.com/shirriff/Arduino-IRremote/ @@ -7,6 +7,7 @@ /// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1062 /// @see http://elektrolab.wz.cz/katalog/samsung_protocol.pdf /// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1538 (Checksum) +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1277 (Timers) // Supports: // Brand: Samsung, Model: UA55H6300 TV (SAMSUNG) @@ -18,11 +19,13 @@ // Brand: Samsung, Model: AH59-02692E Soundbar remote (SAMSUNG36) // Brand: Samsung, Model: HW-J551 Soundbar (SAMSUNG36) // Brand: Samsung, Model: AR09FSSDAWKNFA A/C (SAMSUNG_AC) +// Brand: Samsung, Model: AR09HSFSBWKN A/C (SAMSUNG_AC) // Brand: Samsung, Model: AR12KSFPEWQNET A/C (SAMSUNG_AC) // Brand: Samsung, Model: AR12HSSDBWKNEU A/C (SAMSUNG_AC) // Brand: Samsung, Model: AR12NXCXAWKXEU A/C (SAMSUNG_AC) -// Brand: Samsung, Model: AR09HSFSBWKN A/C (SAMSUNG_AC) +// Brand: Samsung, Model: AR12TXEAAWKNEU A/C (SAMSUNG_AC) // Brand: Samsung, Model: DB93-14195A remote (SAMSUNG_AC) +// Brand: Samsung, Model: DB96-24901C remote (SAMSUNG_AC) #ifndef IR_SAMSUNG_H_ #define IR_SAMSUNG_H_ @@ -41,116 +44,125 @@ /// Native representation of a Samsung A/C message. union SamsungProtocol{ uint8_t raw[kSamsungAcExtendedStateLength]; ///< State in code form. - struct { + struct { // Standard message map // Byte 0 - uint8_t :8; + uint8_t :8; // Byte 1 uint8_t :4; - uint8_t Quiet1 :1; - uint8_t Power1 :1; - uint8_t :2; - // Byte 2~4 - uint8_t pad0[3]; + uint8_t :4; // Sum1Lower + // Byte 2 + uint8_t :4; // Sum1Upper + uint8_t :4; + // Byte 3 + uint8_t :8; + // Byte 4 + uint8_t :8; // Byte 5 - uint8_t :5; - uint8_t Quiet5 :1; + uint8_t :4; + uint8_t Sleep5 :1; + uint8_t Quiet :1; uint8_t :2; // Byte 6 uint8_t :4; - uint8_t Power6 :2; + uint8_t Power1 :2; uint8_t :2; // Byte 7 - uint8_t :8; + uint8_t :8; // Byte 8 - uint8_t Powerful8 :8; + uint8_t :4; + uint8_t :4; // Sum2Lower // Byte 9 - uint8_t :4; - uint8_t Swing :3; - uint8_t :1; + uint8_t :4; // Sum1Upper + uint8_t Swing :3; + uint8_t :1; // Byte 10 - uint8_t :1; - uint8_t Powerful10 :3; - uint8_t Display :1; - uint8_t :2; - uint8_t Clean10 :1; + uint8_t :1; + uint8_t FanSpecial :3; // Powerful, Breeze/WindFree, Econo + uint8_t Display :1; + uint8_t :2; + uint8_t CleanToggle10 :1; // Byte 11 - uint8_t Ion :1; - uint8_t Clean11 :1; - uint8_t :2; - uint8_t Temp :4; + uint8_t Ion :1; + uint8_t CleanToggle11 :1; + uint8_t :2; + uint8_t Temp :4; // Byte 12 uint8_t :1; uint8_t Fan :3; uint8_t Mode :3; uint8_t :1; // Byte 13 - uint8_t :1; - uint8_t Beep :1; - uint8_t :6; + uint8_t :2; + uint8_t BeepToggle :1; + uint8_t :1; + uint8_t Power2 :2; + uint8_t :2; }; - struct { + struct { // Extended message map // 1st Section // Byte 0 - uint8_t :8; + uint8_t :8; // Byte 1 - uint8_t :4; - uint8_t Sum1Lower :4; + uint8_t :4; + uint8_t Sum1Lower :4; // Byte 2 - uint8_t Sum1Upper :4; - uint8_t :4; + uint8_t Sum1Upper :4; + uint8_t :4; // Byte 3 - uint8_t :8; + uint8_t :8; // Byte 4 - uint8_t :8; + uint8_t :8; // Byte 5 - uint8_t :8; + uint8_t :8; // Byte 6 - uint8_t :8; + uint8_t :8; // 2nd Section // Byte 7 - uint8_t :8; + uint8_t :8; // Byte 8 - uint8_t :4; - uint8_t Sum2Lower :4; + uint8_t :4; + uint8_t Sum2Lower :4; // Byte 9 - uint8_t Sum2Upper :4; - uint8_t :4; + uint8_t Sum2Upper :4; + uint8_t OffTimeMins :3; // In units of 10's of mins + uint8_t OffTimeHrs1 :1; // LSB of the number of hours. // Byte 10 - uint8_t :1; - uint8_t Breeze :3; // WindFree - uint8_t :4; + uint8_t OffTimeHrs2 :4; // MSBs of the number of hours. + uint8_t OnTimeMins :3; // In units of 10's of mins + uint8_t OnTimeHrs1 :1; // LSB of the number of hours. // Byte 11 - uint8_t :8; + uint8_t OnTimeHrs2 :4; // MSBs of the number of hours. + uint8_t :4; // Byte 12 - uint8_t :8; + uint8_t OffTimeDay :1; + uint8_t OnTimerEnable :1; + uint8_t OffTimerEnable :1; + uint8_t Sleep12 :1; + uint8_t OnTimeDay :1; + uint8_t :3; // Byte 13 - uint8_t :8; + uint8_t :8; // 3rd Section // Byte 14 - uint8_t :8; + uint8_t :8; // Byte 15 - uint8_t :4; - uint8_t Sum3Lower :4; + uint8_t :4; + uint8_t Sum3Lower :4; // Byte 16 - uint8_t Sum3Upper :4; - uint8_t :4; + uint8_t Sum3Upper :4; + uint8_t :4; // Byte 17 - uint8_t :8; + uint8_t :8; // Byte 18 - uint8_t :8; + uint8_t :8; // Byte 19 - uint8_t :8; + uint8_t :8; // Byte 20 - uint8_t :8; + uint8_t :8; }; }; // Constants -const uint8_t kSamsungAcPowerfulMask8 = 0b01010000; -const uint8_t kSamsungAcSwingMove = 0b010; -const uint8_t kSamsungAcSwingStop = 0b111; -const uint8_t kSamsungAcPowerful10On = 0b011; -const uint8_t kSamsungAcBreezeOn = 0b101; const uint8_t kSamsungAcMinTemp = 16; // C Mask 0b11110000 const uint8_t kSamsungAcMaxTemp = 30; // C Mask 0b11110000 const uint8_t kSamsungAcAutoTemp = 25; // C Mask 0b11110000 @@ -174,12 +186,10 @@ class IRSamsungAc { public: explicit IRSamsungAc(const uint16_t pin, const bool inverted = false, const bool use_modulation = true); - void stateReset(const bool forcepower = true, const bool initialPower = true); + void stateReset(const bool extended = true, const bool initialPower = true); #if SEND_SAMSUNG_AC - void send(const uint16_t repeat = kSamsungAcDefaultRepeat, - const bool calcchecksum = true); - void sendExtended(const uint16_t repeat = kSamsungAcDefaultRepeat, - const bool calcchecksum = true); + void send(const uint16_t repeat = kSamsungAcDefaultRepeat); + void sendExtended(const uint16_t repeat = kSamsungAcDefaultRepeat); void sendOn(const uint16_t repeat = kSamsungAcDefaultRepeat); void sendOff(const uint16_t repeat = kSamsungAcDefaultRepeat); /// Run the calibration to calculate uSec timing offsets for this platform. @@ -201,6 +211,8 @@ class IRSamsungAc { uint8_t getMode(void) const; void setSwing(const bool on); bool getSwing(void) const; + void setSwingH(const bool on); + bool getSwingH(void) const; void setBeep(const bool on); bool getBeep(void) const; void setClean(const bool on); @@ -211,10 +223,18 @@ class IRSamsungAc { bool getPowerful(void) const; void setBreeze(const bool on); bool getBreeze(void) const; + void setEcono(const bool on); + bool getEcono(void) const; void setDisplay(const bool on); bool getDisplay(void) const; void setIon(const bool on); bool getIon(void) const; + uint16_t getOnTimer(void) const; + void setOnTimer(const uint16_t nr_of_mins); + uint16_t getOffTimer(void) const; + void setOffTimer(const uint16_t nr_of_mins); + uint16_t getSleepTimer(void) const; + void setSleepTimer(const uint16_t nr_of_mins); uint8_t* getRaw(void); void setRaw(const uint8_t new_code[], const uint16_t length = kSamsungAcStateLength); @@ -238,9 +258,22 @@ class IRSamsungAc { /// @endcond #endif // UNIT_TEST SamsungProtocol _; - bool _forcepower; ///< Hack to know when we need to send a special power mesg + bool _forceextended; ///< Flag to know when we need to send an extended mesg. bool _lastsentpowerstate; + bool _OnTimerEnable; + bool _OffTimerEnable; + bool _Sleep; + bool _lastSleep; + uint16_t _OnTimer; + uint16_t _OffTimer; + uint16_t _lastOnTimer; + uint16_t _lastOffTimer; void checksum(void); + uint16_t _getOnTimer(void) const; + uint16_t _getOffTimer(void) const; + void _setOnTimer(void); + void _setOffTimer(void); + void _setSleepTimer(void); }; #endif // IR_SAMSUNG_H_ diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Sharp.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Sharp.cpp index 8cbace41e..38f0ac32c 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Sharp.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Sharp.cpp @@ -45,7 +45,9 @@ using irutils::addIntToString; using irutils::addLabeledString; using irutils::addModeToString; using irutils::addModelToString; +using irutils::addSwingVToString; using irutils::addTempToString; +using irutils::addToggleToString; using irutils::minsToString; // Also used by Denon protocol @@ -544,24 +546,73 @@ void IRSharpAc::setTurbo(const bool on) { _.Special = kSharpAcSpecialTurbo; } +/// Get the Vertical Swing setting of the A/C. +/// @return The position of the Vertical Swing setting. +uint8_t IRSharpAc::getSwingV(void) const { return _.Swing; } + +/// Set the Vertical Swing setting of the A/C. +/// @note Some positions may not work on all models. +/// @param[in] position The desired position/setting. +/// @note `setSwingV(kSharpAcSwingVLowest)` will only allow the Lowest setting +/// in Heat mode, it will default to `kSharpAcSwingVLow` otherwise. +/// If you want to set this value in other modes e.g. Cool, you must +/// use `setSwingV`s optional `force` parameter. +/// @param[in] force Do we override the safety checks and just do it? +void IRSharpAc::setSwingV(const uint8_t position, const bool force) { + switch (position) { + case kSharpAcSwingVCoanda: + // Only allowed in Heat mode. + if (!force && getMode() != kSharpAcHeat) { + setSwingV(kSharpAcSwingVLow); // Use the next lowest setting. + return; + } + // FALLTHRU + case kSharpAcSwingVHigh: + case kSharpAcSwingVMid: + case kSharpAcSwingVLow: + case kSharpAcSwingVToggle: + case kSharpAcSwingVOff: + case kSharpAcSwingVLast: // Technically valid, but we don't use it. + // All expected non-positions set the special bits. + _.Special = kSharpAcSpecialSwing; + // FALLTHRU + case kSharpAcSwingVIgnore: + _.Swing = position; + } +} + +/// Convert a standard A/C vertical swing into its native setting. +/// @param[in] position A stdAc::swingv_t position to convert. +/// @return The equivalent native horizontal swing position. +uint8_t IRSharpAc::convertSwingV(const stdAc::swingv_t position) { + switch (position) { + case stdAc::swingv_t::kHighest: + case stdAc::swingv_t::kHigh: return kSharpAcSwingVHigh; + case stdAc::swingv_t::kMiddle: return kSharpAcSwingVMid; + case stdAc::swingv_t::kLow: return kSharpAcSwingVLow; + case stdAc::swingv_t::kLowest: return kSharpAcSwingVCoanda; + case stdAc::swingv_t::kAuto: return kSharpAcSwingVToggle; + case stdAc::swingv_t::kOff: return kSharpAcSwingVOff; + default: return kSharpAcSwingVIgnore; + } +} + /// Get the (vertical) Swing Toggle setting of the A/C. /// @return true, the setting is on. false, the setting is off. bool IRSharpAc::getSwingToggle(void) const { - return _.Swing == kSharpAcSwingToggle; + return getSwingV() == kSharpAcSwingVToggle; } /// Set the (vertical) Swing Toggle setting of the A/C. /// @param[in] on true, the setting is on. false, the setting is off. void IRSharpAc::setSwingToggle(const bool on) { - _.Swing = (on ? kSharpAcSwingToggle : kSharpAcSwingNoToggle); + setSwingV(on ? kSharpAcSwingVToggle : kSharpAcSwingVIgnore); if (on) _.Special = kSharpAcSpecialSwing; } /// Get the Ion (Filter) setting of the A/C. /// @return true, the setting is on. false, the setting is off. -bool IRSharpAc::getIon(void) const { - return _.Ion; -} +bool IRSharpAc::getIon(void) const { return _.Ion; } /// Set the Ion (Filter) setting of the A/C. /// @param[in] on true, the setting is on. false, the setting is off. @@ -628,15 +679,11 @@ uint16_t IRSharpAc::getTimerTime(void) const { /// Is the Timer enabled? /// @return true, the setting is on. false, the setting is off. -bool IRSharpAc::getTimerEnabled(void) const { - return _.TimerEnabled; -} +bool IRSharpAc::getTimerEnabled(void) const { return _.TimerEnabled; } /// Get the current timer type. /// @return true, It's an "On" timer. false, It's an "Off" timer. -bool IRSharpAc::getTimerType(void) const { - return _.TimerType; -} +bool IRSharpAc::getTimerType(void) const { return _.TimerType; } /// Set or cancel the timer function. /// @param[in] enable Is the timer to be enabled (true) or canceled(false)? @@ -765,10 +812,34 @@ stdAc::fanspeed_t IRSharpAc::toCommonFanSpeed(const uint8_t speed) const { } } +/// Convert a native vertical swing postion to it's common equivalent. +/// @param[in] pos A native position to convert. +/// @param[in] mode What operating mode are we in? +/// @return The common vertical swing position. +stdAc::swingv_t IRSharpAc::toCommonSwingV(const uint8_t pos, + const stdAc::opmode_t mode) const { + switch (pos) { + case kSharpAcSwingVHigh: return stdAc::swingv_t::kHighest; + case kSharpAcSwingVMid: return stdAc::swingv_t::kMiddle; + case kSharpAcSwingVLow: return stdAc::swingv_t::kLow; + case kSharpAcSwingVCoanda: // Coanda has mode dependent positionss + switch (mode) { + case stdAc::opmode_t::kCool: return stdAc::swingv_t::kHighest; + case stdAc::opmode_t::kHeat: return stdAc::swingv_t::kLowest; + default: return stdAc::swingv_t::kOff; + } + case kSharpAcSwingVToggle: return stdAc::swingv_t::kAuto; + default: return stdAc::swingv_t::kOff; + } +} + /// Convert the current internal state into its stdAc::state_t equivalent. +/// @param[in] prev Ptr to the previous state if required. /// @return The stdAc equivalent of the native settings. -stdAc::state_t IRSharpAc::toCommon(void) const { +stdAc::state_t IRSharpAc::toCommon(const stdAc::state_t *prev) const { stdAc::state_t result; + // Start with the previous state if given it. + if (prev != NULL) result = *prev; result.protocol = decode_type_t::SHARP_AC; result.model = getModel(); result.power = getPower(); @@ -777,8 +848,8 @@ stdAc::state_t IRSharpAc::toCommon(void) const { result.degrees = getTemp(); result.fanspeed = toCommonFanSpeed(_.Fan); result.turbo = getTurbo(); - result.swingv = getSwingToggle() ? stdAc::swingv_t::kAuto - : stdAc::swingv_t::kOff; + if (getSwingV() != kSharpAcSwingVIgnore) + result.swingv = toCommonSwingV(getSwingV(), result.mode); result.filter = _.Ion; result.econo = getEconoToggle(); result.light = getLightToggle(); @@ -797,14 +868,16 @@ stdAc::state_t IRSharpAc::toCommon(void) const { String IRSharpAc::toString(void) const { String result = ""; const sharp_ac_remote_model_t model = getModel(); - result.reserve(160); // Reserve some heap for the string to reduce fragging. + result.reserve(170); // Reserve some heap for the string to reduce fragging. result += addModelToString(decode_type_t::SHARP_AC, getModel(), false); - result += addLabeledString(isPowerSpecial() ? "-" - : (getPower() ? kOnStr : kOffStr), + result += addLabeledString(isPowerSpecial() ? String("-") + : String(getPower() ? kOnStr + : kOffStr), kPowerStr); + const uint8_t mode = _.Mode; result += addModeToString( - _.Mode, + mode, // Make the value invalid if the model doesn't support an Auto mode. (model == sharp_ac_remote_model_t::A907) ? kSharpAcAuto : 255, kSharpAcCool, kSharpAcHeat, kSharpAcDry, kSharpAcFan); @@ -821,18 +894,37 @@ String IRSharpAc::toString(void) const { kSharpAcFanAuto, kSharpAcFanAuto, kSharpAcFanMed); } + if (getSwingV() == kSharpAcSwingVIgnore) { + result += addIntToString(kSharpAcSwingVIgnore, kSwingVStr); + result += kSpaceLBraceStr; + result += kNAStr; + result += ')'; + } else { + result += addSwingVToString( + getSwingV(), 0xFF, + // Coanda means Highest when in Cool mode. + (mode == kSharpAcCool) ? kSharpAcSwingVCoanda : kSharpAcSwingVToggle, + kSharpAcSwingVHigh, + 0xFF, // Upper Middle is unused + kSharpAcSwingVMid, + 0xFF, // Lower Middle is unused + kSharpAcSwingVLow, + kSharpAcSwingVCoanda, + kSharpAcSwingVOff, + // Below are unused. + kSharpAcSwingVToggle, + 0xFF, + 0xFF); + } result += addBoolToString(getTurbo(), kTurboStr); - result += addBoolToString(getSwingToggle(), kSwingVToggleStr); result += addBoolToString(_.Ion, kIonStr); switch (model) { case sharp_ac_remote_model_t::A705: case sharp_ac_remote_model_t::A903: - result += addLabeledString(getLightToggle() ? kToggleStr : "-", - kLightStr); + result += addToggleToString(getLightToggle(), kLightStr); break; default: - result += addLabeledString(getEconoToggle() ? kToggleStr : "-", - kEconoStr); + result += addToggleToString(getEconoToggle(), kEconoStr); } result += addBoolToString(_.Clean, kCleanStr); if (_.TimerEnabled) diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Sharp.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Sharp.h index dd6d826ac..b3be534e7 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Sharp.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Sharp.h @@ -17,6 +17,7 @@ // Brand: Sharp, Model: AY-ZP40KR A/C (A907) // Brand: Sharp, Model: AH-AxSAY A/C (A907) // Brand: Sharp, Model: CRMC-A907 JBEZ remote (A907) +// Brand: Sharp, Model: CRMC-A950 JBEZ (A907) // Brand: Sharp, Model: AH-PR13-GL A/C (A903) // Brand: Sharp, Model: CRMC-A903JBEZ remote (A903) // Brand: Sharp, Model: AH-XP10NRY A/C (A903) @@ -121,8 +122,23 @@ const uint8_t kSharpAcTimerHoursMax = 0b1100; // 12 const uint8_t kSharpAcOffTimerType = 0b0; const uint8_t kSharpAcOnTimerType = 0b1; -const uint8_t kSharpAcSwingToggle = 0b111; -const uint8_t kSharpAcSwingNoToggle = 0b000; +// Ref: https://github.com/crankyoldgit/IRremoteESP8266/discussions/1590#discussioncomment-1260213 +const uint8_t kSharpAcSwingVIgnore = 0b000; // Don't change the swing setting. +const uint8_t kSharpAcSwingVHigh = 0b001; // 0° down. Similar to Cool Coanda. +const uint8_t kSharpAcSwingVOff = 0b010; // Stop & Go to last fixed pos. +const uint8_t kSharpAcSwingVMid = 0b011; // 30° down +const uint8_t kSharpAcSwingVLow = 0b100; // 45° down +const uint8_t kSharpAcSwingVLast = 0b101; // Same as kSharpAcSwingVOff. +// Toggles between last fixed pos & either 75° down (Heat) or 0° down (Cool) +// i.e. alternate between last pos <-> 75° down if in Heat mode, AND +// alternate between last pos <-> 0° down if in Cool mode. +// Note: `setSwingV(kSharpAcSwingVLowest)` will only allow the Lowest setting in +// Heat mode, it will default to `kSharpAcSwingVLow` otherwise. +// If you want to set this value in other modes e.g. Cool, you must +// use `setSwingV`s optional `force` parameter. +const uint8_t kSharpAcSwingVLowest = 0b110; +const uint8_t kSharpAcSwingVCoanda = kSharpAcSwingVLowest; +const uint8_t kSharpAcSwingVToggle = 0b111; // Toggle Constant swinging on/off. const uint8_t kSharpAcSpecialPower = 0x00; const uint8_t kSharpAcSpecialTurbo = 0x01; @@ -166,6 +182,8 @@ class IRSharpAc { void setTurbo(const bool on); bool getSwingToggle(void) const; void setSwingToggle(const bool on); + uint8_t getSwingV(void) const; + void setSwingV(const uint8_t position, const bool force = false); bool getIon(void) const; void setIon(const bool on); bool getEconoToggle(void) const; @@ -187,9 +205,13 @@ class IRSharpAc { static uint8_t convertFan(const stdAc::fanspeed_t speed, const sharp_ac_remote_model_t model = sharp_ac_remote_model_t::A907); + static uint8_t convertSwingV(const stdAc::swingv_t position); stdAc::opmode_t toCommonMode(const uint8_t mode) const; stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed) const; - stdAc::state_t toCommon(void) const; + stdAc::swingv_t toCommonSwingV( + const uint8_t pos, + const stdAc::opmode_t mode = stdAc::opmode_t::kHeat) const; + stdAc::state_t toCommon(const stdAc::state_t *prev = NULL) const; String toString(void) const; #ifndef UNIT_TEST diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Symphony.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Symphony.cpp index d5fedb29b..b629ef72d 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Symphony.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Symphony.cpp @@ -18,6 +18,15 @@ // Brand: Satellite Electronic, Model: ID6 Remote // Brand: Satellite Electronic, Model: JY199I Fan driver // Brand: Satellite Electronic, Model: JY199I-L Fan driver +// Brand: SilverCrest, Model: SSVS 85 A1 Fan + +// Known Codes: +// SilverCrest SSVS 85 A1 Fan: +// 0x581 - On/Off +// 0x582 - Speed +// 0x584 - Mist +// 0x588 - Timer +// 0x590 - OSC #include #include "IRrecv.h" diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Tcl.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Tcl.cpp index cce9d1f4c..a9e8784a3 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Tcl.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Tcl.cpp @@ -15,12 +15,18 @@ // Constants +const uint8_t kTcl112AcTimerResolution = 20; // Minutes +const uint16_t kTcl112AcTimerMax = 720; // Minutes (12 hrs) + using irutils::addBoolToString; using irutils::addFanToString; using irutils::addIntToString; using irutils::addLabeledString; using irutils::addModeToString; +using irutils::addModelToString; +using irutils::addSwingVToString; using irutils::addTempFloatToString; +using irutils::minsToString; #if SEND_TCL112AC /// Send a TCL 112-bit A/C message. @@ -71,6 +77,8 @@ void IRTcl112Ac::send(const uint16_t repeat) { _quiet_prev = _quiet; // Restore the old state. setRaw(save); + // Make sure it looks like a normal TCL mesg if needed. + if (_.MsgType == kTcl112AcNormal) _.isTcl = true; } // Send the normal (type 1) state. _irsend.sendTcl112Ac(getRaw(), kTcl112AcStateLength, repeat); @@ -109,6 +117,17 @@ bool IRTcl112Ac::validChecksum(uint8_t state[], const uint16_t length) { return (length > 1 && state[length - 1] == calcChecksum(state, length)); } +/// Check the supplied state looks like a TCL112AC message. +/// @param[in] state The array to verify the checksum of. +/// @note Assumes the state is the correct size. +/// @return true, if the state looks like a TCL112AC message. Otherwise, false. +/// @warning This is just a guess. +bool IRTcl112Ac::isTcl(const uint8_t state[]) { + Tcl112Protocol mesg; + std::memcpy(mesg.raw, state, kTcl112AcStateLength); + return (mesg.MsgType != kTcl112AcNormal) || mesg.isTcl; +} + /// Reset the internal state of the emulation. (On, Cool, 24C) void IRTcl112Ac::stateReset(void) { // A known good state. (On, Cool, 24C) @@ -121,6 +140,19 @@ void IRTcl112Ac::stateReset(void) { _quiet_explictly_set = false; } +/// Get/Detect the model of the A/C. +/// @return The enum of the compatible model. +tcl_ac_remote_model_t IRTcl112Ac::getModel(void) const { + return isTcl(_.raw) ? tcl_ac_remote_model_t::TAC09CHSD + : tcl_ac_remote_model_t::GZ055BE1; +} + +/// Set the model of the A/C to emulate. +/// @param[in] model The enum of the appropriate model. +void IRTcl112Ac::setModel(const tcl_ac_remote_model_t model) { + _.isTcl = (model != tcl_ac_remote_model_t::GZ055BE1); +} + /// Get a PTR to the internal state/code for this protocol. /// @return PTR to a code for this protocol based on the current internal state. uint8_t* IRTcl112Ac::getRaw(void) { @@ -203,6 +235,7 @@ float IRTcl112Ac::getTemp(void) const { void IRTcl112Ac::setFan(const uint8_t speed) { switch (speed) { case kTcl112AcFanAuto: + case kTcl112AcFanMin: case kTcl112AcFanLow: case kTcl112AcFanMed: case kTcl112AcFanHigh: @@ -250,14 +283,23 @@ void IRTcl112Ac::setSwingHorizontal(const bool on) { _.SwingH = on; } bool IRTcl112Ac::getSwingHorizontal(void) const { return _.SwingH; } /// Set the vertical swing setting of the A/C. -/// @param[in] on true, the setting is on. false, the setting is off. -void IRTcl112Ac::setSwingVertical(const bool on) { - _.SwingV = (on ? kTcl112AcSwingVOn : kTcl112AcSwingVOff); +/// @param[in] setting The value of the desired setting. +void IRTcl112Ac::setSwingVertical(const uint8_t setting) { + switch (setting) { + case kTcl112AcSwingVOff: + case kTcl112AcSwingVHighest: + case kTcl112AcSwingVHigh: + case kTcl112AcSwingVMiddle: + case kTcl112AcSwingVLow: + case kTcl112AcSwingVLowest: + case kTcl112AcSwingVOn: + _.SwingV = setting; + } } /// Get the vertical swing setting of the A/C. -/// @return true, the setting is on. false, the setting is off. -bool IRTcl112Ac::getSwingVertical(void) const { return _.SwingV; } +/// @return The current setting. +uint8_t IRTcl112Ac::getSwingVertical(void) const { return _.SwingV; } /// Set the Turbo setting of the A/C. /// @param[in] on true, the setting is on. false, the setting is off. @@ -291,6 +333,36 @@ bool IRTcl112Ac::getQuiet(const bool def) const { return _quiet_explictly_set ? _quiet : def; } +/// Get how long the On Timer is set for, in minutes. +/// @return The time in nr of minutes. +uint16_t IRTcl112Ac::getOnTimer(void) const { + return _.OnTimer * kTcl112AcTimerResolution; +} + +/// Set or cancel the On Timer function. +/// @param[in] mins Nr. of minutes the timer is to be set to. +/// @note Rounds down to 20 min increments. (max: 720 mins (12h), 0 is Off) +void IRTcl112Ac::setOnTimer(const uint16_t mins) { + _.OnTimer = std::min(mins, kTcl112AcTimerMax) / kTcl112AcTimerResolution; + _.OnTimerEnabled = _.OnTimer > 0; + _.TimerIndicator = _.OnTimerEnabled || _.OffTimerEnabled; +} + +/// Get how long the Off Timer is set for, in minutes. +/// @return The time in nr of minutes. +uint16_t IRTcl112Ac::getOffTimer(void) const { + return _.OffTimer * kTcl112AcTimerResolution; +} + +/// Set or cancel the Off Timer function. +/// @param[in] mins Nr. of minutes the timer is to be set to. +/// @note Rounds down to 20 min increments. (max: 720 mins (12h), 0 is Off) +void IRTcl112Ac::setOffTimer(const uint16_t mins) { + _.OffTimer = std::min(mins, kTcl112AcTimerMax) / kTcl112AcTimerResolution; + _.OffTimerEnabled = _.OffTimer > 0; + _.TimerIndicator = _.OnTimerEnabled || _.OffTimerEnabled; +} + /// Convert a stdAc::opmode_t enum into its native mode. /// @param[in] mode The enum to be converted. /// @return The native equivalent of the enum. @@ -309,7 +381,7 @@ uint8_t IRTcl112Ac::convertMode(const stdAc::opmode_t mode) { /// @return The native equivalent of the enum. uint8_t IRTcl112Ac::convertFan(const stdAc::fanspeed_t speed) { switch (speed) { - case stdAc::fanspeed_t::kMin: + case stdAc::fanspeed_t::kMin: return kTcl112AcFanMin; case stdAc::fanspeed_t::kLow: return kTcl112AcFanLow; case stdAc::fanspeed_t::kMedium: return kTcl112AcFanMed; case stdAc::fanspeed_t::kHigh: @@ -331,6 +403,21 @@ stdAc::opmode_t IRTcl112Ac::toCommonMode(const uint8_t mode) { } } +/// Convert a stdAc::swingv_t enum into it's native setting. +/// @param[in] position The enum to be converted. +/// @return The native equivalent of the enum. +uint8_t IRTcl112Ac::convertSwingV(const stdAc::swingv_t position) { + switch (position) { + case stdAc::swingv_t::kOff: return kTcl112AcSwingVOff; + case stdAc::swingv_t::kHighest: return kTcl112AcSwingVHighest; + case stdAc::swingv_t::kHigh: return kTcl112AcSwingVHigh; + case stdAc::swingv_t::kMiddle: return kTcl112AcSwingVMiddle; + case stdAc::swingv_t::kLow: return kTcl112AcSwingVLow; + case stdAc::swingv_t::kLowest: return kTcl112AcSwingVLowest; + default: return kTcl112AcSwingVOn; + } +} + /// Convert a native fan speed into its stdAc equivalent. /// @param[in] spd The native setting to be converted. /// @return The stdAc equivalent of the native setting. @@ -338,11 +425,21 @@ stdAc::fanspeed_t IRTcl112Ac::toCommonFanSpeed(const uint8_t spd) { switch (spd) { case kTcl112AcFanHigh: return stdAc::fanspeed_t::kMax; case kTcl112AcFanMed: return stdAc::fanspeed_t::kMedium; - case kTcl112AcFanLow: return stdAc::fanspeed_t::kMin; + case kTcl112AcFanLow: return stdAc::fanspeed_t::kLow; + case kTcl112AcFanMin: return stdAc::fanspeed_t::kMin; default: return stdAc::fanspeed_t::kAuto; } } +/// Convert a native vertical swing postion to it's common equivalent. +/// @param[in] setting A native position to convert. +/// @return The common vertical swing position. +stdAc::swingv_t IRTcl112Ac::toCommonSwingV(const uint8_t setting) { + switch (setting) { + case kTcl112AcSwingVOff: return stdAc::swingv_t::kOff; + default: return stdAc::swingv_t::kAuto; + } +} /// Convert the current internal state into its stdAc::state_t equivalent. /// @param[in] prev Ptr to the previous state if required. /// @return The stdAc equivalent of the native settings. @@ -351,7 +448,7 @@ stdAc::state_t IRTcl112Ac::toCommon(const stdAc::state_t *prev) const { // Start with the previous state if given it. if (prev != NULL) result = *prev; result.protocol = decode_type_t::TCL112AC; - result.model = -1; // Not supported. + result.model = getModel(); result.quiet = getQuiet(result.quiet); // The rest only get updated if it is a "normal" message. if (_.MsgType == kTcl112AcNormal) { @@ -360,7 +457,7 @@ stdAc::state_t IRTcl112Ac::toCommon(const stdAc::state_t *prev) const { result.celsius = true; result.degrees = getTemp(); result.fanspeed = toCommonFanSpeed(_.Fan); - result.swingv = _.SwingV ? stdAc::swingv_t::kAuto : stdAc::swingv_t::kOff; + result.swingv = toCommonSwingV(_.SwingV); result.swingh = _.SwingH ? stdAc::swingh_t::kAuto : stdAc::swingh_t::kOff; result.turbo = _.Turbo; result.filter = _.Health; @@ -379,8 +476,10 @@ stdAc::state_t IRTcl112Ac::toCommon(const stdAc::state_t *prev) const { /// @return A human readable string. String IRTcl112Ac::toString(void) const { String result = ""; - result.reserve(150); // Reserve some heap for the string to reduce fragging. - result += addIntToString(_.MsgType, D_STR_TYPE, false); + result.reserve(220); // Reserve some heap for the string to reduce fragging. + tcl_ac_remote_model_t model = getModel(); + result += addModelToString(decode_type_t::TCL112AC, model, false); + result += addIntToString(_.MsgType, D_STR_TYPE); switch (_.MsgType) { case kTcl112AcNormal: result += addBoolToString(_.Power, kPowerStr); @@ -388,14 +487,32 @@ String IRTcl112Ac::toString(void) const { kTcl112AcHeat, kTcl112AcDry, kTcl112AcFan); result += addTempFloatToString(getTemp()); result += addFanToString(_.Fan, kTcl112AcFanHigh, kTcl112AcFanLow, - kTcl112AcFanAuto, kTcl112AcFanAuto, + kTcl112AcFanAuto, kTcl112AcFanMin, kTcl112AcFanMed); - result += addBoolToString(_.Econo, kEconoStr); - result += addBoolToString(_.Health, kHealthStr); - result += addBoolToString(_.Turbo, kTurboStr); - result += addBoolToString(_.SwingH, kSwingHStr); - result += addBoolToString(_.SwingV, kSwingVStr); - result += addBoolToString(getLight(), kLightStr); + result += addSwingVToString(_.SwingV, kTcl112AcSwingVOff, + kTcl112AcSwingVHighest, + kTcl112AcSwingVHigh, + 0xFF, // unused + kTcl112AcSwingVMiddle, + 0xFF, // unused + kTcl112AcSwingVLow, + kTcl112AcSwingVLowest, + kTcl112AcSwingVOff, + kTcl112AcSwingVOn, // Swing + 0xFF, 0xFF); // Both Unused + if (model != tcl_ac_remote_model_t::GZ055BE1) { + result += addBoolToString(_.SwingH, kSwingHStr); + result += addBoolToString(_.Econo, kEconoStr); + result += addBoolToString(_.Health, kHealthStr); + result += addBoolToString(_.Turbo, kTurboStr); + result += addBoolToString(getLight(), kLightStr); + } + result += addLabeledString( + _.OnTimerEnabled ? minsToString(getOnTimer()) : kOffStr, + kOnTimerStr); + result += addLabeledString( + _.OffTimerEnabled ? minsToString(getOffTimer()) : kOffStr, + kOffTimerStr); break; case kTcl112AcSpecial: result += addBoolToString(_.Quiet, kQuietStr); diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Tcl.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Tcl.h index b9f059627..e1696c42a 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Tcl.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Tcl.h @@ -4,8 +4,10 @@ /// @brief Support for TCL protocols. // Supports: -// Brand: Leberg, Model: LBS-TOR07 A/C -// Brand: TCL, Model: TAC-09CHSD/XA31I A/C +// Brand: Leberg, Model: LBS-TOR07 A/C (TAC09CHSD) +// Brand: TCL, Model: TAC-09CHSD/XA31I A/C (TAC09CHSD) +// Brand: Teknopoint, Model: Allegro SSA-09H A/C (GZ055BE1) +// Brand: Teknopoint, Model: GZ-055B-E1 remote (GZ055BE1) #ifndef IR_TCL_H_ #define IR_TCL_H_ @@ -25,41 +27,54 @@ union Tcl112Protocol{ uint8_t raw[kTcl112AcStateLength]; ///< The State in IR code form. struct { // Byte 0~2 - uint8_t pad0[3]; + uint8_t :8; + uint8_t :8; + uint8_t :8; // Byte 3 - uint8_t MsgType :2; - uint8_t :6; + uint8_t MsgType :2; + uint8_t :6; // Byte 4 - uint8_t :8; + uint8_t :8; // Byte 5 - uint8_t :2; - uint8_t Power :1; - uint8_t :2; - uint8_t Quiet :1; - uint8_t Light :1; - uint8_t Econo :1; + uint8_t :2; + uint8_t Power :1; + uint8_t OffTimerEnabled :1; + uint8_t OnTimerEnabled :1; + uint8_t Quiet :1; + uint8_t Light :1; + uint8_t Econo :1; // Byte 6 - uint8_t Mode :4; - uint8_t Health :1; - uint8_t Turbo :1; - uint8_t :2; + uint8_t Mode :4; + uint8_t Health :1; + uint8_t Turbo :1; + uint8_t :2; // Byte 7 - uint8_t Temp :4; - uint8_t :4; + uint8_t Temp :4; + uint8_t :4; // Byte 8 - uint8_t Fan :3; - uint8_t SwingV :3; - uint8_t :2; - // Byte 9~11 - uint8_t pad1[3]; + uint8_t Fan :3; + uint8_t SwingV :3; + uint8_t TimerIndicator :1; + uint8_t :1; + // Byte 9 + uint8_t :1; // 0 + uint8_t OffTimer :6; + uint8_t :1; // 0 + // Byte 10 + uint8_t :1; // 0 + uint8_t OnTimer :6; + uint8_t :1; // 0 + // Byte 11 + uint8_t :8; // 00000000 // Byte 12 - uint8_t :3; - uint8_t SwingH :1; - uint8_t :1; - uint8_t HalfDegree :1; - uint8_t :2; + uint8_t :3; + uint8_t SwingH :1; + uint8_t :1; + uint8_t HalfDegree :1; + uint8_t :1; + uint8_t isTcl :1; // Byte 13 - uint8_t Sum :8; + uint8_t Sum :8; }; }; @@ -81,15 +96,23 @@ const uint8_t kTcl112AcFan = 7; const uint8_t kTcl112AcAuto = 8; const uint8_t kTcl112AcFanAuto = 0b000; +const uint8_t kTcl112AcFanMin = 0b001; // Aka. "Night" const uint8_t kTcl112AcFanLow = 0b010; const uint8_t kTcl112AcFanMed = 0b011; const uint8_t kTcl112AcFanHigh = 0b101; +const uint8_t kTcl112AcFanNight = kTcl112AcFanMin; +const uint8_t kTcl112AcFanQuiet = kTcl112AcFanMin; const float kTcl112AcTempMax = 31.0; const float kTcl112AcTempMin = 16.0; -const uint8_t kTcl112AcSwingVOn = 0b111; -const uint8_t kTcl112AcSwingVOff = 0b000; +const uint8_t kTcl112AcSwingVOff = 0b000; +const uint8_t kTcl112AcSwingVHighest = 0b001; +const uint8_t kTcl112AcSwingVHigh = 0b010; +const uint8_t kTcl112AcSwingVMiddle = 0b011; +const uint8_t kTcl112AcSwingVLow = 0b100; +const uint8_t kTcl112AcSwingVLowest = 0b101; +const uint8_t kTcl112AcSwingVOn = 0b111; // MsgType const uint8_t kTcl112AcNormal = 0b01; const uint8_t kTcl112AcSpecial = 0b10; @@ -113,6 +136,8 @@ class IRTcl112Ac { uint8_t* getRaw(void); void setRaw(const uint8_t new_code[], const uint16_t length = kTcl112AcStateLength); + tcl_ac_remote_model_t getModel(void) const; + void setModel(const tcl_ac_remote_model_t model); void on(void); void off(void); void setPower(const bool on); @@ -135,16 +160,23 @@ class IRTcl112Ac { bool getLight(void) const; void setSwingHorizontal(const bool on); bool getSwingHorizontal(void) const; - void setSwingVertical(const bool on); - bool getSwingVertical(void) const; + void setSwingVertical(const uint8_t setting); + uint8_t getSwingVertical(void) const; void setTurbo(const bool on); bool getTurbo(void) const; void setQuiet(const bool on); bool getQuiet(const bool def = false) const; + uint16_t getOnTimer(void) const; + void setOnTimer(const uint16_t mins); + uint16_t getOffTimer(void) const; + void setOffTimer(const uint16_t mins); + static bool isTcl(const uint8_t state[]); static uint8_t convertMode(const stdAc::opmode_t mode); static uint8_t convertFan(const stdAc::fanspeed_t speed); + static uint8_t convertSwingV(const stdAc::swingv_t position); static stdAc::opmode_t toCommonMode(const uint8_t mode); static stdAc::fanspeed_t toCommonFanSpeed(const uint8_t speed); + static stdAc::swingv_t toCommonSwingV(const uint8_t setting); stdAc::state_t toCommon(const stdAc::state_t *prev = NULL) const; String toString(void) const; #ifndef UNIT_TEST diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Transcold.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Transcold.cpp index 066196073..14cc7f8bd 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Transcold.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/ir_Transcold.cpp @@ -29,7 +29,7 @@ using irutils::addIntToString; using irutils::addLabeledString; using irutils::addModeToString; using irutils::addTempToString; - +using irutils::addToggleToString; #if SEND_TRANSCOLD /// Send a Transcold message @@ -391,13 +391,7 @@ String IRTranscoldAc::toString(void) const { result += addBoolToString(getPower(), kPowerStr, false); if (!getPower()) return result; // If it's off, there is no other info. // Special modes. - if (getSwing()) { - result += kCommaSpaceStr; - result += kSwingStr; - result += kColonSpaceStr; - result += kToggleStr; - return result; - } + if (getSwing()) return result + addToggleToString(true, kSwingStr); result += addModeToString(getMode(), kTranscoldAuto, kTranscoldCool, kTranscoldHeat, kTranscoldDry, kTranscoldFan); result += addIntToString(_.Fan, kFanStr); diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/locale/defaults.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/locale/defaults.h index b55b87abc..0fcc04791 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/locale/defaults.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/locale/defaults.h @@ -30,9 +30,15 @@ #ifndef D_STR_ON #define D_STR_ON "On" #endif // D_STR_ON +#ifndef D_STR_1 +#define D_STR_1 "1" +#endif // D_STR_1 #ifndef D_STR_OFF #define D_STR_OFF "Off" #endif // D_STR_OFF +#ifndef D_STR_0 +#define D_STR_0 "0" +#endif // D_STR_0 #ifndef D_STR_MODE #define D_STR_MODE "Mode" #endif // D_STR_MODE @@ -285,6 +291,9 @@ #ifndef D_STR_VANE #define D_STR_VANE "Vane" #endif // D_STR_VANE +#ifndef D_STR_LOCK +#define D_STR_LOCK "Lock" +#endif // D_STR_LOCK #ifndef D_STR_AUTO #define D_STR_AUTO "Auto" @@ -298,18 +307,42 @@ #ifndef D_STR_COOL #define D_STR_COOL "Cool" #endif // D_STR_COOL +#ifndef D_STR_COOLING +#define D_STR_COOLING "Cooling" +#endif // D_STR_COOLING #ifndef D_STR_HEAT #define D_STR_HEAT "Heat" #endif // D_STR_HEAT +#ifndef D_STR_HEATING +#define D_STR_HEATING "Heating" +#endif // D_STR_HEATING #ifndef D_STR_FAN #define D_STR_FAN "Fan" #endif // D_STR_FAN #ifndef D_STR_FANONLY -#define D_STR_FANONLY "fan_only" +#define D_STR_FANONLY "fan-only" #endif // D_STR_FANONLY +#ifndef D_STR_FAN_ONLY +#define D_STR_FAN_ONLY "fan_only" +#endif // D_STR_FAN_ONLY +#ifndef D_STR_ONLY +#define D_STR_ONLY "Only" +#endif // D_STR_ONLY +#ifndef D_STR_FANSPACEONLY +#define D_STR_FANSPACEONLY D_STR_FAN " " D_STR_ONLY +#endif // D_STR_FANSPACEONLY +#ifndef D_STR_FANONLYNOSPACE +#define D_STR_FANONLYNOSPACE D_STR_FAN D_STR_ONLY +#endif // D_STR_FANONLYNOSPACE #ifndef D_STR_DRY #define D_STR_DRY "Dry" #endif // D_STR_DRY +#ifndef D_STR_DRYING +#define D_STR_DRYING "Drying" +#endif // D_STR_DRYING +#ifndef D_STR_DEHUMIDIFY +#define D_STR_DEHUMIDIFY "Dehumidify" +#endif // D_STR_DEHUMIDIFY #ifndef D_STR_MAX #define D_STR_MAX "Max" @@ -360,6 +393,12 @@ #ifndef D_STR_MAXRIGHT #define D_STR_MAXRIGHT D_STR_MAX " " D_STR_RIGHT // Set `D_STR_MAX` first! #endif // D_STR_MAXRIGHT +#ifndef D_STR_MAXRIGHT_NOSPACE +#define D_STR_MAXRIGHT_NOSPACE D_STR_MAX D_STR_RIGHT // Set `D_STR_MAX` first! +#endif // D_STR_MAXRIGHT_NOSPACE +#ifndef D_STR_RIGHTMAX +#define D_STR_RIGHTMAX D_STR_RIGHT " " D_STR_MAX // Set `D_STR_MAX` first! +#endif // D_STR_RIGHTMAX #ifndef D_STR_RIGHTMAX_NOSPACE #define D_STR_RIGHTMAX_NOSPACE D_STR_RIGHT D_STR_MAX // Set `D_STR_MAX` first! #endif // D_STR_RIGHTMAX_NOSPACE @@ -369,6 +408,12 @@ #ifndef D_STR_MAXLEFT #define D_STR_MAXLEFT D_STR_MAX " " D_STR_LEFT // Set `D_STR_MAX` first! #endif // D_STR_MAXLEFT +#ifndef D_STR_MAXLEFT_NOSPACE +#define D_STR_MAXLEFT_NOSPACE D_STR_MAX D_STR_LEFT // Set `D_STR_MAX` first! +#endif // D_STR_MAXLEFT_NOSPACE +#ifndef D_STR_LEFTMAX +#define D_STR_LEFTMAX D_STR_LEFT " " D_STR_MAX // Set `D_STR_MAX` first! +#endif // D_STR_LEFTMAX #ifndef D_STR_LEFTMAX_NOSPACE #define D_STR_LEFTMAX_NOSPACE D_STR_LEFT D_STR_MAX // Set `D_STR_MAX` first! #endif // D_STR_LEFTMAX_NOSPACE @@ -440,6 +485,9 @@ #ifndef D_STR_COLONSPACE #define D_STR_COLONSPACE ": " #endif // D_STR_COLONSPACE +#ifndef D_STR_DASH +#define D_STR_DASH "-" +#endif // D_STR_DASH #ifndef D_STR_DAY #define D_STR_DAY "Day" @@ -495,7 +543,135 @@ #define D_STR_BITS "Bits" #endif // D_STR_BITS +// Model Names +#ifndef D_STR_YAW1F +#define D_STR_YAW1F "YAW1F" +#endif // D_STR_YAW1F +#ifndef D_STR_YBOFB +#define D_STR_YBOFB "YBOFB" +#endif // D_STR_YBOFB +#ifndef D_STR_V9014557_A +#define D_STR_V9014557_A "V9014557-A" +#endif // D_STR_V9014557_A +#ifndef D_STR_V9014557_B +#define D_STR_V9014557_B "V9014557-B" +#endif // D_STR_V9014557_B +#ifndef D_STR_RLT0541HTA_A +#define D_STR_RLT0541HTA_A "R-LT0541-HTA-A" +#endif // D_STR_RLT0541HTA_A +#ifndef D_STR_RLT0541HTA_B +#define D_STR_RLT0541HTA_B "R-LT0541-HTA-B" +#endif // D_STR_RLT0541HTA_B +#ifndef D_STR_ARRAH2E +#define D_STR_ARRAH2E "ARRAH2E" +#endif // D_STR_ARRAH2E +#ifndef D_STR_ARDB1 +#define D_STR_ARDB1 "ARDB1" +#endif // D_STR_ARDB1 +#ifndef D_STR_ARREB1E +#define D_STR_ARREB1E "ARREB1E" +#endif // D_STR_ARREB1E +#ifndef D_STR_ARJW2 +#define D_STR_ARJW2 "ARJW2" +#endif // D_STR_ARJW2 +#ifndef D_STR_ARRY4 +#define D_STR_ARRY4 "ARRY4" +#endif // D_STR_ARRY4 +#ifndef D_STR_ARREW4E +#define D_STR_ARREW4E "ARREW4E" +#endif // D_STR_ARREW4E +#ifndef D_STR_GE6711AR2853M +#define D_STR_GE6711AR2853M "GE6711AR2853M" +#endif // D_STR_GE6711AR2853M +#ifndef D_STR_AKB75215403 +#define D_STR_AKB75215403 "AKB75215403" +#endif // D_STR_AKB75215403 +#ifndef D_STR_AKB74955603 +#define D_STR_AKB74955603 "AKB74955603" +#endif // D_STR_AKB74955603 +#ifndef D_STR_AKB73757604 +#define D_STR_AKB73757604 "AKB73757604" +#endif // D_STR_AKB73757604 +#ifndef D_STR_KKG9AC1 +#define D_STR_KKG9AC1 "KKG9AC1" +#endif // D_STR_KKG9AC1 +#ifndef D_STR_KKG29AC1 +#define D_STR_KKG29AC1 "KKG29AC1" +#endif // D_STR_KKG9AC1 +#ifndef D_STR_LKE +#define D_STR_LKE "LKE" +#endif // D_STR_LKE +#ifndef D_STR_NKE +#define D_STR_NKE "NKE" +#endif // D_STR_NKE +#ifndef D_STR_DKE +#define D_STR_DKE "DKE" +#endif // D_STR_DKE +#ifndef D_STR_PKR +#define D_STR_PKR "PKR" +#endif // D_STR_PKR +#ifndef D_STR_JKE +#define D_STR_JKE "JKE" +#endif // D_STR_JKE +#ifndef D_STR_CKP +#define D_STR_CKP "CKP" +#endif // D_STR_CKP +#ifndef D_STR_RKR +#define D_STR_RKR "RKR" +#endif // D_STR_RKR +#ifndef D_STR_PANASONICLKE +#define D_STR_PANASONICLKE "PANASONICLKE" +#endif // D_STR_PANASONICLKE +#ifndef D_STR_PANASONICNKE +#define D_STR_PANASONICNKE "PANASONICNKE" +#endif // D_STR_PANASONICNKE +#ifndef D_STR_PANASONICDKE +#define D_STR_PANASONICDKE "PANASONICDKE" +#endif // D_STR_PANASONICDKE +#ifndef D_STR_PANASONICPKR +#define D_STR_PANASONICPKR "PANASONICPKR" +#endif // D_STR_PANASONICPKR +#ifndef D_STR_PANASONICJKE +#define D_STR_PANASONICJKE "PANASONICJKE" +#endif // D_STR_PANASONICJKE +#ifndef D_STR_PANASONICCKP +#define D_STR_PANASONICCKP "PANASONICCKP" +#endif // D_STR_PANASONICCKP +#ifndef D_STR_PANASONICRKR +#define D_STR_PANASONICRKR "PANASONICRKR" +#endif // D_STR_PANASONICRKR +#ifndef D_STR_A907 +#define D_STR_A907 "A907" +#endif // D_STR_A907 +#ifndef D_STR_A705 +#define D_STR_A705 "A705" +#endif // D_STR_A705 +#ifndef D_STR_A903 +#define D_STR_A903 "A903" +#endif // D_STR_A903 +#ifndef D_STR_TAC09CHSD +#define D_STR_TAC09CHSD "TAC09CHSD" +#endif // D_STR_TAC09CHSD +#ifndef D_STR_GZ055BE1 +#define D_STR_GZ055BE1 "GZ055BE1" +#endif // D_STR_GZ055BE1 +#ifndef D_STR_122LZF +#define D_STR_122LZF "122LZF" +#endif // D_STR_122LZF +#ifndef D_STR_DG11J13A +#define D_STR_DG11J13A "DG11J13A" +#endif // D_STR_DG11J13A +#ifndef D_STR_DG11J104 +#define D_STR_DG11J104 "DG11J104" +#endif // D_STR_DG11J104 +#ifndef D_STR_DG11J191 +#define D_STR_DG11J191 "DG11J191" +#endif // D_STR_DG11J191 + // Protocols Names +#ifndef D_STR_AIRTON +#define D_STR_AIRTON "AIRTON" +#endif // D_STR_AIRTON #ifndef D_STR_AIRWELL #define D_STR_AIRWELL "AIRWELL" #endif // D_STR_AIRWELL @@ -508,6 +684,9 @@ #ifndef D_STR_ARGO #define D_STR_ARGO "ARGO" #endif // D_STR_ARGO +#ifndef D_STR_ARRIS +#define D_STR_ARRIS "ARRIS" +#endif // D_STR_ARRIS #ifndef D_STR_BOSE #define D_STR_BOSE "BOSE" #endif // D_STR_BOSE @@ -733,6 +912,9 @@ #ifndef D_STR_RCMM #define D_STR_RCMM "RCMM" #endif // D_STR_RCMM +#ifndef D_STR_RHOSS +#define D_STR_RHOSS "RHOSS" +#endif // D_STR_RHOSS #ifndef D_STR_SAMSUNG #define D_STR_SAMSUNG "SAMSUNG" #endif // D_STR_SAMSUNG diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/locale/pt-BR.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/locale/pt-BR.h index 4875dda0d..4b2c929e0 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/locale/pt-BR.h +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/locale/pt-BR.h @@ -29,6 +29,7 @@ #define D_STR_TIMER "Timer" #define D_STR_ONTIMER D_STR_TIMER " " D_STR_ON #define D_STR_OFFTIMER D_STR_TIMER " " D_STR_OFF +#define D_STR_TIMERMODE D_STR_MODE " " D_STR_TIMER #define D_STR_CLOCK "Relógio" #define D_STR_COMMAND "Comando" #define D_STR_HEALTH "Saúde" @@ -84,6 +85,11 @@ #define D_STR_6THSENSE "Sexto sentido" #define D_STR_ZONEFOLLOW "Acompanhar ambiente" #define D_STR_FIXED "Fixo" +#define D_STR_TYPE "Tipo" +#define D_STR_SPECIAL "Especial" +#define D_STR_RECYCLE "Reciclar" +#define D_STR_ID "Id" +#define D_STR_VANE "Vane" #define D_STR_AUTO "Auto" #define D_STR_AUTOMATIC "Automático" @@ -91,7 +97,11 @@ #define D_STR_COOL "Esfriar" #define D_STR_HEAT "Aquecer" #define D_STR_FAN "Ventilar" -#define D_STR_FANONLY "Apenas ventilar" +#define D_STR_FANONLY "Apenas-ventilar" +#define D_STR_FAN_ONLY "Apenas_ventilar" +#define D_STR_ONLY "Apenas" +#define D_STR_FANSPACEONLY D_STR_ONLY " " D_STR_FAN +#define D_STR_FANONLYNOSPACE D_STR_ONLY D_STR_FAN #define D_STR_DRY "Secar" #define D_STR_8C_HEAT D_STR_HEAT " 8C" diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/locale/ru-RU.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/locale/ru-RU.h new file mode 100644 index 000000000..02a892403 --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/locale/ru-RU.h @@ -0,0 +1,152 @@ +// Copyright 2021 - PtilopsisLeucotis (@PtilopsisLeucotis) +// Locale/language file for Russian / Russia. +// This file will override the default values located in `defaults.h`. +#ifndef LOCALE_RU_RU_H_ +#define LOCALE_RU_RU_H_ + +#define D_STR_UNKNOWN "НЕИЗВЕСТНО" +#define D_STR_PROTOCOL "Протокол" +#define D_STR_POWER "Питание" +#define D_STR_PREVIOUS "Предыдущий" +#define D_STR_ON "Вкл" +#define D_STR_OFF "Выкл" +#define D_STR_MODE "Режим" +#define D_STR_TOGGLE "Переключить" +#define D_STR_TURBO "Турбо" +#define D_STR_SUPER "Супер" +#define D_STR_SLEEP "Сон" +#define D_STR_LIGHT "Свет" +#define D_STR_POWERFUL "Мощный" +#define D_STR_QUIET "Тихий" +#define D_STR_ECONO "Экономичный" +#define D_STR_SWING "Качание" +#define D_STR_SWINGH D_STR_SWING"(Г)" +#define D_STR_SWINGV D_STR_SWING"(В)" +#define D_STR_BEEP "Звук" +#define D_STR_MOULD "Плесень" +#define D_STR_CLEAN "Чистый" +#define D_STR_PURIFY "Очистка" +#define D_STR_TIMER "Таймер" +#define D_STR_ONTIMER "Таймер Включения" +#define D_STR_OFFTIMER "Таймер Выключения" +#define D_STR_TIMERMODE "Режим Таймера" +#define D_STR_CLOCK "Часы" +#define D_STR_COMMAND "Команда" +#define D_STR_HEALTH "Здоровье" +#define D_STR_MODEL "Модель" +#define D_STR_TEMP "Температура" +#define D_STR_HUMID "Влажность" +#define D_STR_SAVE "Сохранить" +#define D_STR_EYE "Глаз" +#define D_STR_FOLLOW "Следовать" +#define D_STR_ION "Ион" +#define D_STR_FRESH "Свежесть" +#define D_STR_HOLD "Удержать" +#define D_STR_BUTTON "Кнопка" +#define D_STR_NIGHT "Ночь" +#define D_STR_SILENT "Тихий" +#define D_STR_FILTER "Фильтр" +#define D_STR_CELSIUS "Цельсий" +#define D_STR_FAHRENHEIT "Фаренгейт" +#define D_STR_UP "Выше" +#define D_STR_TEMPUP D_STR_TEMP " " D_STR_UP +#define D_STR_DOWN "Ниже" +#define D_STR_TEMPDOWN D_STR_TEMP " " D_STR_DOWN +#define D_STR_CHANGE "Изменение" +#define D_STR_START "Запуск" +#define D_STR_STOP "Остановка" +#define D_STR_MOVE "Перемещение" +#define D_STR_SET "Установка" +#define D_STR_CANCEL "Отмена" +#define D_STR_COMFORT "Комфорт" +#define D_STR_SENSOR "Сенсор" +#define D_STR_DISPLAY "Дисплей" +#define D_STR_WEEKLY "Недельный" +#define D_STR_LAST "Последний" +#define D_STR_FAST "Быстро" +#define D_STR_SLOW "Медленно" +#define D_STR_AIRFLOW "Воздушный Поток" +#define D_STR_STEP "Шаг" +#define D_STR_NA "Н/Д" +#define D_STR_INSIDE "Внутри" +#define D_STR_OUTSIDE "Снаружи" +#define D_STR_LOUD "Громко" +#define D_STR_UPPER "Верхнее" +#define D_STR_LOWER "Нижнее" +#define D_STR_BREEZE "Бриз" +#define D_STR_CIRCULATE "Циркуляция" +#define D_STR_CEILING "Потолок" +#define D_STR_WALL "Стена" +#define D_STR_ROOM "Комната" +#define D_STR_6THSENSE "6-ое чувство" +#define D_STR_FIXED "Фиксированный" +#define D_STR_TYPE "Тип" +#define D_STR_SPECIAL "Специальный" +#define D_STR_RECYCLE "Рециркуляция" +#define D_STR_VANE "Жалюзи" +#define D_STR_LOCK "Блокировка" +#define D_STR_AUTO "Авто" +#define D_STR_AUTOMATIC "Автоматический" +#define D_STR_MANUAL "Ручной" +#define D_STR_COOL "Охл" +#define D_STR_COOLING "Охлаждение" +#define D_STR_HEAT "Нагр" +#define D_STR_HEATING "Обогрев" +#define D_STR_FAN "Вентиляция" +#define D_STR_ONLY "Только" +#define D_STR_FANSPACEONLY D_STR_ONLY " " D_STR_FAN +#define D_STR_FANONLYNOSPACE D_STR_ONLY D_STR_FAN +#define D_STR_DRY "Сухо" +#define D_STR_DRYING "Сушка" +#define D_STR_DEHUMIDIFY "Осушение" +#define D_STR_MAX "Макс" +#define D_STR_MAXIMUM "Максимум" +#define D_STR_MIN "Мин" +#define D_STR_MINIMUM "Минимум" +#define D_STR_MED "Сред" +#define D_STR_MEDIUM "Среднее" +#define D_STR_HIGHEST "Верхнее" +#define D_STR_HIGH "Верх" +#define D_STR_HI "Верх" +#define D_STR_MID "Сред" +#define D_STR_MIDDLE "Середина" +#define D_STR_LOW "Низ" +#define D_STR_LO "Низ" +#define D_STR_LOWEST "Нижнее" +#define D_STR_RIGHT "Право" +#define D_STR_LEFT "Лево" +#define D_STR_WIDE "Широкий" +#define D_STR_CENTRE "Центр" +#define D_STR_TOP "Наивысший" +#define D_STR_BOTTOM "Наинизший" +#define D_STR_DAY "День" +#define D_STR_DAYS "Дней" +#define D_STR_HOUR "Час" +#define D_STR_HOURS "Часов" +#define D_STR_MINUTE "Минута" +#define D_STR_MINUTES "Минут" +#define D_STR_SECOND "Секунда" +#define D_STR_SECONDS "Секунд" +#define D_STR_NOW "Сейчас" +#define D_STR_THREELETTERDAYS "ВскПндВтрСреЧтвПтнСуб" +#define D_STR_YES "Да" +#define D_STR_NO "Нет" +#define D_STR_TRUE "Истина" +#define D_STR_FALSE "Ложь" +#define D_STR_REPEAT "Повтор" +#define D_STR_CODE "Код" +#define D_STR_BITS "Бит" + +// IRrecvDumpV2+ +#define D_STR_TIMESTAMP "Метка Времени" +#define D_STR_LIBRARY "Библиотека" +#define D_STR_MESGDESC "Описание Сообщения." +#define D_STR_TOLERANCE "Допуск" +#define D_STR_IRRECVDUMP_STARTUP \ + "IRrecvDump запущен и ождает ИК команды на Входе %d" +#define D_WARN_BUFFERFULL \ + "ПРЕДУПРЕЖДЕНИЕ: ИК код слишком велик для буфера (>= %d). " \ + "Этому результату не следует доверять, пока это не будет исправлено. " \ + "Исправьте и увеличьте `kCaptureBufferSize`." + +#endif // LOCALE_RU_RU_H_ diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/locale/sv-SE.h b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/locale/sv-SE.h new file mode 100644 index 000000000..b82ec42bc --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/src/locale/sv-SE.h @@ -0,0 +1,189 @@ +// Copyright 2021 - Tom Rosenback (@tomrosenback) +// Locale/language file for swedish / Sweden. +// This file will override the default values located in `defaults.h`. +#ifndef LOCALE_SV_SE_H_ +#define LOCALE_SV_SE_H_ + +#define D_STR_UNKNOWN "OKÄND" +#define D_STR_PROTOCOL "Protokoll" +#define D_STR_POWER "Strömläge" +#define D_STR_PREVIOUS "Föregående" +#define D_STR_ON "På" +#define D_STR_OFF "Av" +#define D_STR_MODE "Läge" +#define D_STR_TOGGLE "Växla" +#define D_STR_TURBO "Turbo" +#define D_STR_SUPER "Super" +#define D_STR_SLEEP "Sova" +#define D_STR_LIGHT "Svag" +#define D_STR_POWERFUL "Kraftig" +#define D_STR_QUIET "Tyst" +#define D_STR_ECONO "Eko" +#define D_STR_SWING "Sving" +#define D_STR_SWINGH D_STR_SWING"(H)" +#define D_STR_SWINGV D_STR_SWING"(V)" +#define D_STR_BEEP "Pip" +#define D_STR_MOULD "Forma" +#define D_STR_CLEAN "Rengör" +#define D_STR_PURIFY "Rena" +#define D_STR_TIMER "Timer" +#define D_STR_ONTIMER "På timer" +#define D_STR_OFFTIMER "Av timer" +#define D_STR_TIMERMODE "Timerläge" +#define D_STR_CLOCK "Klocka" +#define D_STR_COMMAND "Kommando" +#define D_STR_XFAN "XFan" +#define D_STR_HEALTH "Hälsa" +#define D_STR_MODEL "Modell" +#define D_STR_TEMP "Temp" +#define D_STR_IFEEL "Känns som" +#define D_STR_HUMID "Humid" +#define D_STR_SAVE "Save" +#define D_STR_EYE "Öga" +#define D_STR_FOLLOW "Följ" +#define D_STR_ION "Ion" +#define D_STR_FRESH "Frisk" +#define D_STR_HOLD "Håll" +#define D_STR_8C_HEAT "8C " D_STR_HEAT +#define D_STR_10C_HEAT "10C " D_STR_HEAT +#define D_STR_BUTTON "Knapp" +#define D_STR_NIGHT "Natt" +#define D_STR_SILENT "Tyst" +#define D_STR_FILTER "Filter" +#define D_STR_3D "3D" +#define D_STR_CELSIUS "Celsius" +#define D_STR_FAHRENHEIT "Fahrenheit" +#define D_STR_CELSIUS_FAHRENHEIT D_STR_CELSIUS "/" D_STR_FAHRENHEIT +#define D_STR_UP "Upp" +#define D_STR_TEMPUP D_STR_TEMP " upp" +#define D_STR_DOWN "Ner" +#define D_STR_TEMPDOWN D_STR_TEMP " ner" +#define D_STR_CHANGE "Ändra" +#define D_STR_START "Starta" +#define D_STR_STOP "Stoppa" +#define D_STR_MOVE "Flytta" +#define D_STR_SET "Ställ in" +#define D_STR_CANCEL "Avbryt" +#define D_STR_COMFORT "Komfort" +#define D_STR_SENSOR "Sensor" +#define D_STR_DISPLAY "Display" +#define D_STR_WEEKLY "Veckovis" +#define D_STR_WEEKLYTIMER D_STR_WEEKLY " timer" +#define D_STR_WIFI "WiFi" +#define D_STR_LAST "Senast" +#define D_STR_FAST "Snabb" +#define D_STR_SLOW "Sakta" +#define D_STR_AIRFLOW "Luftflöde" +#define D_STR_STEP "Steppa" +#define D_STR_NA "N/A" +#define D_STR_INSIDE "Inne" +#define D_STR_OUTSIDE "Ute" +#define D_STR_LOUD "Hög" +#define D_STR_UPPER "Övre" +#define D_STR_LOWER "Nedre" +#define D_STR_BREEZE "Bris" +#define D_STR_CIRCULATE "Cirkulera" +#define D_STR_CEILING "Tak" +#define D_STR_WALL "Vägg" +#define D_STR_ROOM "Rum" +#define D_STR_6THSENSE "6e sinne" +#define D_STR_ZONEFOLLOW "Följ zon" +#define D_STR_FIXED "Fast" +#define D_STR_TYPE "Typ" +#define D_STR_SPECIAL "Speciell" +#define D_STR_RECYCLE "Återvinn" +#define D_STR_ID "Id" +#define D_STR_VANE "Vindflöjel" + +#define D_STR_AUTO "Auto" +#define D_STR_AUTOMATIC "Automatisk" +#define D_STR_MANUAL "Manuell" +#define D_STR_COOL "Kyla" +#define D_STR_HEAT "Värme" +#define D_STR_FAN "Fläkt" +#define D_STR_FANONLY "fläkt-enbart" +#define D_STR_FAN_ONLY "fläkt_enbart" +#define D_STR_ONLY "Enbart" +#define D_STR_FANSPACEONLY D_STR_FAN " " D_STR_ONLY +#define D_STR_FANONLYNOSPACE D_STR_FAN D_STR_ONLY +#define D_STR_DRY "Torka" + +#define D_STR_MAX "Max" +#define D_STR_MAXIMUM "Maximum" +#define D_STR_MIN "Min" +#define D_STR_MINIMUM "Minimum" +#define D_STR_MED "Med" +#define D_STR_MEDIUM "Medium" + +#define D_STR_HIGHEST "Högsta" +#define D_STR_HIGH "Hög" +#define D_STR_HI "Hög" +#define D_STR_MID "Mellan" +#define D_STR_MIDDLE "Mellan" +#define D_STR_LOW "Låg" +#define D_STR_LO "Låg" +#define D_STR_LOWEST "Lägsta" +#define D_STR_RIGHT "Höger" +#define D_STR_MAXRIGHT D_STR_MAX " höger" +#define D_STR_RIGHTMAX_NOSPACE D_STR_MAX D_STR_RIGHT +#define D_STR_LEFT "Vänster" +#define D_STR_MAXLEFT D_STR_MAX " vänster" +#define D_STR_LEFTMAX_NOSPACE D_STR_MAX D_STR_LEFT +#define D_STR_WIDE "Vid" +#define D_STR_CENTRE "Mitten" +#define D_STR_TOP "Topp" +#define D_STR_BOTTOM "Botten" + +#define D_STR_ECONOTOGGLE D_STR_TOGGLE " eko" +#define D_STR_EYEAUTO D_STR_AUTO " öga" +#define D_STR_LIGHTTOGGLE D_STR_TOGGLE " svag" +#define D_STR_OUTSIDEQUIET D_STR_QUIET " ute" +#define D_STR_POWERTOGGLE D_STR_TOGGLE " strömläge" +#define D_STR_POWERBUTTON "Strömknapp" +#define D_STR_PREVIOUSPOWER "Föregående strömläge" +#define D_STR_DISPLAYTEMP "Displaytemp" +#define D_STR_SENSORTEMP "Sensortemp" +#define D_STR_SLEEP_TIMER "Sovtimer" +#define D_STR_SWINGVMODE D_STR_SWINGV " läge" +#define D_STR_SWINGVTOGGLE D_STR_TOGGLE " sving(v)" +#define D_STR_TURBOTOGGLE D_STR_TOGGLE " turbo" + +// Separatorer +#define D_CHR_TIME_SEP ':' +#define D_STR_SPACELBRACE " (" +#define D_STR_COMMASPACE ", " +#define D_STR_COLONSPACE ": " + +#define D_STR_DAY "Dag" +#define D_STR_DAYS D_STR_DAY "ar" +#define D_STR_HOUR "Timme" +#define D_STR_HOURS "Timmar" +#define D_STR_MINUTE "Minut" +#define D_STR_MINUTES D_STR_MINUTE "er" +#define D_STR_SECOND "Sekund" +#define D_STR_SECONDS D_STR_MINUTE "er" +#define D_STR_NOW "Nu" +#define D_STR_THREELETTERDAYS "SönMånTisOnsTorFreLör" + +#define D_STR_YES "Ja" +#define D_STR_NO "Nej" +#define D_STR_TRUE "Sant" +#define D_STR_FALSE "Falskt" + +#define D_STR_REPEAT "Upprepa" +#define D_STR_CODE "Kod" +#define D_STR_BITS "Bitar" + +// IRrecvDumpV2+ +#define D_STR_TIMESTAMP "Tidskod" +#define D_STR_LIBRARY "Bibliotek" +#define D_STR_MESGDESC "Meddelande beskr." +#define D_STR_TOLERANCE "Tolerans" +#define D_STR_IRRECVDUMP_STARTUP \ + "IRrecvDump har nu startats och väntar på IR signaler på PIN %d" +#define D_WARN_BUFFERFULL \ + "VARNING: IR koden är för stor för att rymmas i bufferminnet (>= %d). " \ + "Detta resultat är inte pålitligt innan problemet är åtgärdat. " \ + "Redigera och öka `kCaptureBufferSize`." + +#endif // LOCALE_SV_SE_H_ diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/IRac_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/IRac_test.cpp index 140e50137..d43cfcd9d 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/IRac_test.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/IRac_test.cpp @@ -19,6 +19,7 @@ #include "ir_Kelvinator.h" #include "ir_LG.h" #include "ir_Midea.h" +#include "ir_Mirage.h" #include "ir_Mitsubishi.h" #include "ir_MitsubishiHeavy.h" #include "ir_Neoclima.h" @@ -560,7 +561,8 @@ TEST(TestIRac, Electra) { IRrecv capture(kGpioUnused); char expected[] = "Power: On, Mode: 6 (Fan), Temp: 26C, Fan: 1 (High), " - "Swing(V): On, Swing(H): On, Light: Toggle, Clean: On, Turbo: On"; + "Swing(V): On, Swing(H): On, Light: Toggle, Clean: On, Turbo: On, " + "IFeel: Off"; ac.begin(); irac.electra(&ac, @@ -727,9 +729,10 @@ TEST(TestIRac, Gree) { IRrecv capture(kGpioUnused); char expected[] = "Model: 1 (YAW1F), Power: On, Mode: 1 (Cool), Temp: 71F, " - "Fan: 2 (Medium), Turbo: Off, IFeel: Off, WiFi: Off, XFan: On, " - "Light: On, Sleep: On, Swing(V) Mode: Manual, " - "Swing(V): 3 (UNKNOWN), Timer: Off, Display Temp: 0 (Off)"; + "Fan: 2 (Medium), Turbo: Off, Econo: Off, IFeel: Off, WiFi: Off, " + "XFan: On, Light: On, Sleep: On, Swing(V) Mode: Manual, " + "Swing(V): 3 (UNKNOWN), Swing(H): 5 (Right), Timer: Off, " + "Display Temp: 0 (Off)"; ac.begin(); irac.gree(&ac, @@ -740,7 +743,9 @@ TEST(TestIRac, Gree) { 71, // Degrees (F) stdAc::fanspeed_t::kMedium, // Fan speed stdAc::swingv_t::kHigh, // Vertical swing + stdAc::swingh_t::kRight, // Horizontal swing false, // Turbo + false, // Econo true, // Light true, // Clean (aka Mold/XFan) 8 * 60 + 0); // Sleep time @@ -760,7 +765,7 @@ TEST(TestIRac, Haier) { IRrecv capture(kGpioUnused); char expected[] = "Command: 1 (On), Mode: 1 (Cool), Temp: 24C, Fan: 2 (Medium), " - "Swing: 1 (Up), Sleep: On, Health: On, Clock: 13:45, " + "Swing(V): 1 (Up), Sleep: On, Health: On, Clock: 13:45, " "On Timer: Off, Off Timer: Off"; ac.begin(); @@ -788,19 +793,24 @@ TEST(TestIRac, Haier176) { IRac irac(kGpioUnused); IRrecv capture(kGpioUnused); const char expected[] = - "Power: On, Button: 5 (Power), Mode: 1 (Cool), Temp: 23C, " - "Fan: 2 (Medium), Turbo: 1 (High), Swing: 1 (Highest), Sleep: On, " - "Health: On, Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off"; + "Model: 1 (V9014557-A), Power: On, Button: 5 (Power), " + "Mode: 1 (Cool), Temp: 23C, Fan: 2 (Medium), Turbo: On, Quiet: Off, " + "Swing(V): 1 (Highest), Swing(H): 0 (Middle), Sleep: On, Health: On, " + "Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off, Lock: Off"; ac.begin(); irac.haier176(&ac, - true, // Power - stdAc::opmode_t::kCool, // Mode - 23, // Celsius - stdAc::fanspeed_t::kMedium, // Fan speed - stdAc::swingv_t::kHigh, // Vertical swing - true, // Turbo - true, // Filter - 8 * 60 + 0); // Sleep time + haier_ac176_remote_model_t::V9014557_A, // Model + true, // Power + stdAc::opmode_t::kCool, // Mode + true, // Celsius + 23, // Degrees + stdAc::fanspeed_t::kMedium, // Fan speed + stdAc::swingv_t::kHigh, // Vertical swing + stdAc::swingh_t::kOff, // Horizontal swing + true, // Turbo + false, // Quiet + true, // Filter + 8 * 60 + 0); // Sleep time ASSERT_EQ(expected, ac.toString()); ac._irsend.makeDecodeResult(); EXPECT_TRUE(capture.decode(&ac._irsend.capture)); @@ -816,20 +826,24 @@ TEST(TestIRac, HaierYrwo2) { IRac irac(kGpioUnused); IRrecv capture(kGpioUnused); char expected[] = - "Power: On, Button: 5 (Power), Mode: 1 (Cool), Temp: 23C, " - "Fan: 2 (Medium), Turbo: 1 (High), Swing: 1 (Highest), Sleep: On, " - "Health: On, Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off"; + "Model: 1 (V9014557-A), Power: On, Button: 5 (Power), " + "Mode: 1 (Cool), Temp: 23C, Fan: 2 (Medium), Turbo: Off, Quiet: On, " + "Swing(V): 1 (Highest), Swing(H): 7 (Auto), Sleep: On, Health: On, " + "Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off, Lock: Off"; ac.begin(); irac.haierYrwo2(&ac, - true, // Power - stdAc::opmode_t::kCool, // Mode - 23, // Celsius - stdAc::fanspeed_t::kMedium, // Fan speed - stdAc::swingv_t::kHigh, // Vertical swing - true, // Turbo - true, // Filter - 8 * 60 + 0); // Sleep time + true, // Power + stdAc::opmode_t::kCool, // Mode + true, // Celsius + 23, // Degrees + stdAc::fanspeed_t::kMedium, // Fan speed + stdAc::swingv_t::kHigh, // Vertical swing + stdAc::swingh_t::kAuto, // Vertical swing + false, // Turbo + true, // Quiet + true, // Filter + 8 * 60 + 0); // Sleep time ASSERT_EQ(expected, ac.toString()); ac._irsend.makeDecodeResult(); EXPECT_TRUE(capture.decode(&ac._irsend.capture)); @@ -1125,7 +1139,22 @@ TEST(TestIRac, Issue1513) { stdAc::swingh_t::kOff, // Horizontal swing true); // Light ac._irsend.makeDecodeResult(); - // All sent, we assume the above works. Just need to switch to swing off now. + EXPECT_EQ(121, ac._irsend.capture.rawlen); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(LG2, ac._irsend.capture.decode_type); // Not "LG" + ASSERT_EQ(kLgBits, ac._irsend.capture.bits); + ASSERT_EQ( + "Model: 2 (AKB75215403), Power: On, Mode: 4 (Heat), Temp: 26C, " + "Fan: 0 (Quiet)", + IRAcUtils::resultAcToString(&ac._irsend.capture)); + + // The next should be a SwingV On. + EXPECT_TRUE(capture.decodeLG(&ac._irsend.capture, 61)); + ASSERT_EQ(LG2, ac._irsend.capture.decode_type); // Not "LG" + ASSERT_EQ(kLgBits, ac._irsend.capture.bits); + EXPECT_EQ(kLgAcSwingVSwing, ac._irsend.capture.value); + ASSERT_EQ("Model: 3 (AKB74955603), Swing(V): 20 (Swing)", + IRAcUtils::resultAcToString(&ac._irsend.capture)); ac._irsend.reset(); ac.stateReset(); ac.send(); @@ -1163,6 +1192,79 @@ TEST(TestIRac, Issue1513) { IRAcUtils::resultAcToString(&ac._irsend.capture)); } +// Ref: +// https://github.com/crankyoldgit/IRremoteESP8266/issues/1651#issuecomment-952811720 +TEST(TestIRac, Issue1651) { + // Simulate sending a state with a SwingV off, then followed by a SwingV Auto. + IRLgAc ac(kGpioUnused); + IRac irac(kGpioUnused); + IRrecv capture(kGpioUnused); + ac.begin(); + // IRhvac {"Vendor":"LG2","Model":3,"Mode":"Auto","Power":"On","Celsius":"On", + // "Temp":15,"FanSpeed":"Auto","SwingV":"Off","SwingH":"Off", + // "Quiet":"Off","Turbo":"Off","Econo":"Off","Light":"On", + // "Filter":"Off","Clean":"Off","Beep":"Off","Sleep":-1} + ac._irsend.reset(); + irac.lg(&ac, + lg_ac_remote_model_t::AKB74955603, // Model + true, // Power + stdAc::opmode_t::kAuto, // Mode + 15, // Degrees C (Note: 16C is min) + stdAc::fanspeed_t::kAuto, // Fan speed + stdAc::swingv_t::kOff, // Vertical swing + stdAc::swingv_t::kOff, // Vertical swing (previous) + stdAc::swingh_t::kOff, // Horizontal swing + true); // Light + ac._irsend.makeDecodeResult(); + // As we are not making a change of the SwingV state, there should only be + // one message. (i.e. 60 + 1) + EXPECT_EQ(61, ac._irsend.capture.rawlen); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(LG2, ac._irsend.capture.decode_type); // Not "LG" + ASSERT_EQ(kLgBits, ac._irsend.capture.bits); + ASSERT_EQ( + "Model: 2 (AKB75215403), Power: On, Mode: 3 (Auto), Temp: 16C, " + "Fan: 5 (Auto)", + IRAcUtils::resultAcToString(&ac._irsend.capture)); + ac._irsend.reset(); + ac.stateReset(); + ac.send(); + // IRhvac {"Vendor":"LG2","Model":3,"Mode":"Auto","Power":"On","Celsius":"On", + // "Temp":15,"FanSpeed":"Max","SwingV":"Auto","SwingH":"Off", + // "Quiet":"Off","Turbo":"Off","Econo":"Off","Light":"On", + // "Filter":"Off","Clean":"Off","Beep":"Off","Sleep":-1} + ac._irsend.makeDecodeResult(); + ac._irsend.reset(); + irac.lg(&ac, + lg_ac_remote_model_t::AKB74955603, // Model + true, // Power + stdAc::opmode_t::kAuto, // Mode + 15, // Degrees C (Note: 16C is min) + stdAc::fanspeed_t::kMax, // Fan speed + stdAc::swingv_t::kAuto, // Vertical swing + stdAc::swingv_t::kOff, // Vertical swing (previous) + stdAc::swingh_t::kOff, // Horizontal swing + true); // Light + ac._irsend.makeDecodeResult(); + // There should only be two messages. + EXPECT_EQ(121, ac._irsend.capture.rawlen); + // First message should be normal. + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(LG2, ac._irsend.capture.decode_type); // Not "LG" + ASSERT_EQ(kLgBits, ac._irsend.capture.bits); + ASSERT_EQ( + "Model: 2 (AKB75215403), Power: On, Mode: 3 (Auto), Temp: 16C, " + "Fan: 4 (Maximum)", + IRAcUtils::resultAcToString(&ac._irsend.capture)); + // The next should be a SwingV Off. + EXPECT_TRUE(capture.decodeLG(&ac._irsend.capture, 61)); + ASSERT_EQ(LG2, ac._irsend.capture.decode_type); // Not "LG" + ASSERT_EQ(kLgBits, ac._irsend.capture.bits); + EXPECT_EQ(kLgAcSwingVSwing, ac._irsend.capture.value); + ASSERT_EQ("Model: 3 (AKB74955603), Swing(V): 20 (Swing)", + IRAcUtils::resultAcToString(&ac._irsend.capture)); +} + TEST(TestIRac, LG2_AKB73757604) { IRLgAc ac(kGpioUnused); IRac irac(kGpioUnused); @@ -1252,6 +1354,62 @@ TEST(TestIRac, Midea) { ASSERT_TRUE(IRAcUtils::decodeToState(&ac._irsend.capture, &r, &p)); } +TEST(TestIRac, Mirage) { + IRMirageAc ac(kGpioUnused); + IRac irac(kGpioUnused); + IRrecv capture(kGpioUnused); + stdAc::state_t state, r, p; + const char expected_KKG9AC1[] = + "Model: 1 (KKG9AC1), Power: On, Mode: 3 (Dry), Temp: 27C, " + "Fan: 2 (Medium), Turbo: Off, Sleep: On, Light: Off, " + "Swing(V): 9 (High), Clock: 17:31"; + + ac.begin(); + + state.model = mirage_ac_remote_model_t::KKG9AC1; + state.power = true; + state.mode = stdAc::opmode_t::kDry; + state.celsius = true; + state.degrees = 27; + state.fanspeed = stdAc::fanspeed_t::kMedium; + state.swingv = stdAc::swingv_t::kHigh; + state.swingh = stdAc::swingh_t::kLeft; + state.turbo = false; + state.quiet = true; + state.light = false; + state.filter = true; + state.clean = false; + state.sleep = 8 * 60 + 0; + state.clock = 17 * 60 + 31; + state.beep = false; + irac.mirage(&ac, state); + + ASSERT_EQ(expected_KKG9AC1, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(MIRAGE, ac._irsend.capture.decode_type); + ASSERT_EQ(kMirageBits, ac._irsend.capture.bits); + ASSERT_EQ(expected_KKG9AC1, IRAcUtils::resultAcToString(&ac._irsend.capture)); + ASSERT_TRUE(IRAcUtils::decodeToState(&ac._irsend.capture, &r, &p)); + + const char expected_KKG29AC1[] = + "Model: 2 (KKG29AC1), Power: On, Mode: 3 (Dry), Temp: 27C, " + "Fan: 3 (Medium), Turbo: Off, Sleep: On, Quiet: On, Light: -, " + "Swing(V): On, Swing(H): On, Filter: On, Clean: -, " + "On Timer: Off, Off Timer: Off, IFeel: Off"; + ac._irsend.reset(); + state.model = mirage_ac_remote_model_t::KKG29AC1; + irac.mirage(&ac, state); + ASSERT_EQ(expected_KKG29AC1, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(MIRAGE, ac._irsend.capture.decode_type); + ASSERT_EQ(kMirageBits, ac._irsend.capture.bits); + ASSERT_EQ(expected_KKG29AC1, + IRAcUtils::resultAcToString(&ac._irsend.capture)); + ASSERT_TRUE(IRAcUtils::decodeToState(&ac._irsend.capture, &r, &p)); +} + TEST(TestIRac, Mitsubishi) { IRMitsubishiAC ac(kGpioUnused); IRac irac(kGpioUnused); @@ -1493,9 +1651,10 @@ TEST(TestIRac, Samsung) { IRSamsungAc ac(kGpioUnused); IRac irac(kGpioUnused); IRrecv capture(kGpioUnused); - char expected[] = - "Power: On, Mode: 0 (Auto), Temp: 28C, Fan: 6 (Auto), Swing: On, " - "Beep: On, Clean: On, Quiet: On, Powerful: Off, Breeze: Off, " + const char expected[] = + "Power: On, Mode: 0 (Auto), Temp: 28C, Fan: 6 (Auto), " + "Swing(V): On, Swing(H): On, Beep: Toggle, " + "Clean: Toggle, Quiet: On, Powerful: Off, ""Econo: Off, Breeze: Off, " "Light: On, Ion: Off"; ac.begin(); @@ -1505,14 +1664,18 @@ TEST(TestIRac, Samsung) { 28, // Celsius stdAc::fanspeed_t::kMedium, // Fan speed stdAc::swingv_t::kAuto, // Vertical swing + stdAc::swingh_t::kAuto, // Horizontal swing true, // Quiet false, // Turbo + false, // Econo true, // Light (Display) false, // Filter (Ion) - true, // Clean + true, // Clean (Toggle) true, // Beep + -1, // Sleep true, // Previous power state - false); // with dopower Off + -1, // Previous Sleep + false); // Force Extended ASSERT_EQ(expected, ac.toString()); ac._irsend.makeDecodeResult(); EXPECT_TRUE(capture.decode(&ac._irsend.capture)); @@ -1529,22 +1692,59 @@ TEST(TestIRac, Samsung) { 28, // Celsius stdAc::fanspeed_t::kMedium, // Fan speed stdAc::swingv_t::kAuto, // Vertical swing + stdAc::swingh_t::kAuto, // Horizontal swing true, // Quiet false, // Turbo + false, // Econo true, // Light (Display) false, // Filter (Ion) - true, // Clean + true, // Clean (Toggle) true, // Beep + -1, // Sleep true, // Previous power state - true); // with dopower On + -1, // Previous Sleep + true); // Force Extended ASSERT_EQ(expected, ac.toString()); // Class should be in the desired mode. ac._irsend.makeDecodeResult(); EXPECT_TRUE(capture.decode(&ac._irsend.capture)); ASSERT_EQ(SAMSUNG_AC, ac._irsend.capture.decode_type); - // We expect an extended state because of `dopower`. + // We expect an extended state because of `Force Extended`. ASSERT_EQ(kSamsungAcExtendedBits, ac._irsend.capture.bits); ASSERT_EQ(expected, IRAcUtils::resultAcToString(&ac._irsend.capture)); ASSERT_TRUE(IRAcUtils::decodeToState(&ac._irsend.capture, &r, &p)); + + ac._irsend.reset(); + const char sleep[] = + "Power: On, Mode: 0 (Auto), Temp: 28C, Fan: 6 (Auto), " + "Swing(V): On, Swing(H): Off, Beep: -, Clean: Toggle, " + "Quiet: On, Powerful: Off, Econo: Off, Breeze: Off, " + "Light: On, Ion: Off, Sleep Timer: 08:00"; + irac.samsung(&ac, + true, // Power + stdAc::opmode_t::kAuto, // Mode + 28, // Celsius + stdAc::fanspeed_t::kMedium, // Fan speed + stdAc::swingv_t::kAuto, // Vertical swing + stdAc::swingh_t::kOff, // Horizontal swing + true, // Quiet + false, // Turbo + false, // Econo + true, // Light (Display) + false, // Filter (Ion) + true, // Clean (Toggle) + false, // Beep + 8 * 60, // Sleep + true, // Previous power state + -1, // Previous Sleep + false); // Force Extended + ASSERT_EQ(sleep, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(SAMSUNG_AC, ac._irsend.capture.decode_type); + // We expect an extended state because of the change in `sleep`. + ASSERT_EQ(kSamsungAcExtendedBits, ac._irsend.capture.bits); + ASSERT_EQ(sleep, IRAcUtils::resultAcToString(&ac._irsend.capture)); + ASSERT_TRUE(IRAcUtils::decodeToState(&ac._irsend.capture, &r, &p)); } TEST(TestIRac, Sanyo) { @@ -1610,7 +1810,7 @@ TEST(TestIRac, Sharp) { IRrecv capture(kGpioUnused); char expected[] = "Model: 1 (A907), Power: On, Mode: 2 (Cool), Temp: 28C, Fan: 3 (Medium), " - "Turbo: Off, Swing(V) Toggle: On, Ion: On, Econo: -, Clean: Off"; + "Swing(V): 7 (Swing), Turbo: Off, Ion: On, Econo: -, Clean: Off"; ac.begin(); irac.sharp(&ac, @@ -1621,6 +1821,7 @@ TEST(TestIRac, Sharp) { 28, // Celsius stdAc::fanspeed_t::kMedium, // Fan speed stdAc::swingv_t::kAuto, // Vertical swing + stdAc::swingv_t::kOff, // Previous Vertical swing false, // Turbo false, // Light true, // Filter (Ion) @@ -1640,23 +1841,25 @@ TEST(TestIRac, Tcl112) { IRac irac(kGpioUnused); IRrecv capture(kGpioUnused); char expected[] = - "Type: 1, Power: On, Mode: 3 (Cool), Temp: 20C, Fan: 3 (Medium), " - "Econo: On, Health: On, Turbo: Off, Swing(H): On, Swing(V): Off, " - "Light: On"; + "Model: 1 (TAC09CHSD), Type: 1, Power: On, Mode: 3 (Cool), Temp: 20C, " + "Fan: 3 (Medium), Swing(V): 0 (Auto), Swing(H): On, " + "Econo: On, Health: On, Turbo: Off, Light: On, " + "On Timer: Off, Off Timer: Off"; ac.begin(); irac.tcl112(&ac, - true, // Power - stdAc::opmode_t::kCool, // Mode - 20, // Celsius - stdAc::fanspeed_t::kMedium, // Fan speed - stdAc::swingv_t::kOff, // Vertical swing - stdAc::swingh_t::kAuto, // Horizontal swing - false, // Quiet (aka. Mute) - false, // Turbo - true, // Light - true, // Econo - true); // Filter (aka. Health) + tcl_ac_remote_model_t::TAC09CHSD, // Model + true, // Power + stdAc::opmode_t::kCool, // Mode + 20, // Celsius + stdAc::fanspeed_t::kMedium, // Fan speed + stdAc::swingv_t::kOff, // Vertical swing + stdAc::swingh_t::kAuto, // Horizontal swing + false, // Quiet (aka. Mute) + false, // Turbo + true, // Light + true, // Econo + true); // Filter (aka. Health) ASSERT_EQ(expected, ac.toString()); ac._irsend.makeDecodeResult(); EXPECT_TRUE(capture.decode(&ac._irsend.capture)); @@ -1668,23 +1871,24 @@ TEST(TestIRac, Tcl112) { // Test the quiet mode, which should generate two messages. ac._irsend.reset(); irac.tcl112(&ac, - true, // Power - stdAc::opmode_t::kCool, // Mode - 20, // Celsius - stdAc::fanspeed_t::kMedium, // Fan speed - stdAc::swingv_t::kOff, // Vertical swing - stdAc::swingh_t::kAuto, // Horizontal swing - true, // Quiet (aka. Mute) - false, // Turbo - true, // Light - true, // Econo - true); // Filter (aka. Health) + tcl_ac_remote_model_t::TAC09CHSD, // Model + true, // Power + stdAc::opmode_t::kCool, // Mode + 20, // Celsius + stdAc::fanspeed_t::kMedium, // Fan speed + stdAc::swingv_t::kOff, // Vertical swing + stdAc::swingh_t::kAuto, // Horizontal swing + true, // Quiet (aka. Mute) + false, // Turbo + true, // Light + true, // Econo + true); // Filter (aka. Health) ac._irsend.makeDecodeResult(); EXPECT_TRUE(capture.decode(&ac._irsend.capture)); ASSERT_EQ(TCL112AC, ac._irsend.capture.decode_type); ASSERT_EQ(kTcl112AcBits, ac._irsend.capture.bits); ASSERT_EQ( - "Type: 2, Quiet: On", + "Model: 1 (TAC09CHSD), Type: 2, Quiet: On", IRAcUtils::resultAcToString(&ac._irsend.capture)); // TCL112 uses the Mitsubishi112 decoder. // Skip first message. @@ -2335,6 +2539,10 @@ TEST(TestIRac, opmodeToString) { EXPECT_EQ("Auto", IRac::opmodeToString(stdAc::opmode_t::kAuto)); EXPECT_EQ("Cool", IRac::opmodeToString(stdAc::opmode_t::kCool)); EXPECT_EQ("UNKNOWN", IRac::opmodeToString((stdAc::opmode_t)500)); + // Home Assistant/Google Home differences. + EXPECT_EQ("Fan", IRac::opmodeToString(stdAc::opmode_t::kFan, false)); + EXPECT_EQ("fan_only", IRac::opmodeToString(stdAc::opmode_t::kFan, true)); + EXPECT_EQ("Fan", IRac::opmodeToString(stdAc::opmode_t::kFan)); // Default } TEST(TestIRac, fanspeedToString) { diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/Makefile b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/Makefile index 132350803..7a193e813 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/Makefile +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/Makefile @@ -3,6 +3,9 @@ # make [all] - makes everything. # make TARGET - makes the given target. # make run - makes everything and runs all the tests. +# make run_tests - run all tests +# make run-% - run specific test file (exclude _test.cpp) +# replace % with given test file, eg run-IRsend # make clean - removes all files generated by make. # make install-googletest - install the googletest code suite @@ -45,6 +48,7 @@ clean : run : all failed=""; \ for unittest in $(TESTS); do \ + echo "RUNNING: $${unittest}"; \ ./$${unittest} || failed="$${failed} $${unittest}"; \ done; \ if [ -n "$${failed}" ]; then \ @@ -55,6 +59,10 @@ run : all run_tests : run +run-% : %_test + echo "RUNNING: $*"; \ + ./$*_test + install-googletest : rm -rf ../lib/googletest git clone -b v1.8.x https://github.com/google/googletest.git ../lib/googletest diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Airton_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Airton_test.cpp new file mode 100644 index 000000000..e4e66ee13 --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Airton_test.cpp @@ -0,0 +1,62 @@ +// Copyright 2021 crankyoldgit + +#include "IRac.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for decodeAirton(). + +TEST(TestDecodeAirton, RealExample) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + const uint16_t rawData[115] = { + 6632, 3352, + 404, 1266, 404, 1264, 406, 430, 406, 430, 400, 1264, 406, 430, 402, 1264, + 408, 1262, 406, 1264, 404, 430, 402, 434, 402, 432, 402, 1264, 406, 430, + 404, 432, 400, 456, 376, 432, 402, 430, 402, 1264, 404, 1264, 404, 432, + 402, 434, 398, 434, 402, 430, 404, 1264, 404, 432, 402, 430, 404, 1264, + 406, 430, 402, 432, 400, 434, 402, 430, 402, 430, 404, 432, 402, 430, + 402, 432, 402, 432, 402, 430, 402, 432, 402, 430, 402, 434, 400, 432, + 402, 1264, 404, 430, 404, 1264, 404, 432, 402, 454, 378, 432, 402, 430, + 404, 1264, 404, 1264, 404, 1264, 378, 1292, 404, 432, 402, 1264, 404, 432, + 402}; + irsend.begin(); + irsend.reset(); + irsend.sendRaw(rawData, 115, 38); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(decode_type_t::AIRTON, irsend.capture.decode_type); + ASSERT_EQ(kAirtonBits, irsend.capture.bits); + EXPECT_EQ(0x5E1400090C11D3, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); +} + +TEST(TestDecodeAirton, SyntheticExample) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + irsend.begin(); + irsend.reset(); + irsend.sendAirton(0x5E1400090C11D3); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(decode_type_t::AIRTON, irsend.capture.decode_type); + ASSERT_EQ(kAirtonBits, irsend.capture.bits); + EXPECT_EQ(0x5E1400090C11D3, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); +} + +TEST(TestUtils, Housekeeping) { + ASSERT_EQ("AIRTON", typeToString(decode_type_t::AIRTON)); + ASSERT_EQ(decode_type_t::AIRTON, strToDecodeType("AIRTON")); + ASSERT_FALSE(hasACState(decode_type_t::AIRTON)); + ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::AIRTON)); + ASSERT_EQ(kAirtonBits, IRsend::defaultBits(decode_type_t::AIRTON)); + ASSERT_EQ(kAirtonDefaultRepeat, IRsend::minRepeats(decode_type_t::AIRTON)); +} diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Arris_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Arris_test.cpp new file mode 100644 index 000000000..2a219b6b2 --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Arris_test.cpp @@ -0,0 +1,189 @@ +// Copyright 2021 David Conran + +#include "IRac.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for decodeArris(). + +// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1595 +// Data from: +// https://github.com/crankyoldgit/IRremoteESP8266/files/7100289/raw_data.txt +TEST(TestDecodeArris, RealExample) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + + const uint16_t rawData_1[59] = { + 2584, 1896, 666, 306, 338, 300, 336, 304, 668, 610, 332, 306, 338, 300, + 334, 304, 332, 312, 332, 306, 340, 300, 334, 304, 330, 308, 338, 302, 334, + 304, 330, 308, 336, 308, 336, 302, 332, 306, 330, 310, 674, 606, 336, 302, + 332, 306, 338, 306, 668, 612, 668, 306, 338, 304, 332, 308, 336, 608, + 334}; // UNKNOWN EDF1C0D0 + + irsend.begin(); + irsend.reset(); + irsend.sendRaw(rawData_1, 59, 38); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(decode_type_t::ARRIS, irsend.capture.decode_type); + EXPECT_EQ(kArrisBits, irsend.capture.bits); + EXPECT_EQ(0x1000085E, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x85, irsend.capture.command); + + irsend.reset(); + const uint16_t rawData_2[115] = { + 2584, 1898, 664, 308, 338, 302, 332, 306, 668, 614, 330, 308, 336, 302, + 332, 306, 340, 304, 330, 310, 336, 304, 332, 306, 338, 300, 334, 304, 330, + 308, 336, 302, 332, 312, 334, 306, 330, 308, 336, 302, 670, 610, 332, 306, + 330, 310, 336, 308, 674, 606, 664, 312, 334, 306, 338, 302, 334, 612, 330, + 5930, + 2584, 1898, 664, 308, 336, 302, 332, 306, 666, 614, 338, 300, 336, 304, + 332, 310, 674, 610, 332, 334, 312, 328, 308, 332, 304, 336, 310, 330, 306, + 332, 302, 314, 330, 336, 308, 330, 306, 334, 640, 612, 330, 308, 336, 302, + 332, 312, 672, 608, 672, 608, 672, 304, 330, 614, 330 + }; // UNKNOWN E6A77D83 + irsend.sendRaw(rawData_2, 115, 38); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(decode_type_t::ARRIS, irsend.capture.decode_type); + EXPECT_EQ(kArrisBits, irsend.capture.bits); + EXPECT_EQ(0x1000085E, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x85, irsend.capture.command); + + const uint16_t rawData_3[51] = { + 2584, 1896, 666, 308, 338, 328, 306, 332, 640, 612, 332, 336, 310, 300, + 334, 304, 678, 606, 336, 330, 306, 334, 310, 300, 334, 304, 332, 308, 338, + 302, 334, 310, 672, 304, 332, 614, 668, 612, 330, 336, 638, 620, 670, 610, + 670, 304, 330, 310, 336, 610, 672}; // UNKNOWN 4CA048A1 + irsend.reset(); + irsend.sendRaw(rawData_3, 51, 38); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(decode_type_t::ARRIS, irsend.capture.decode_type); + EXPECT_EQ(kArrisBits, irsend.capture.bits); + EXPECT_EQ(0x1080695D, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); + EXPECT_EQ(0x695, irsend.capture.command); +} + +TEST(TestDecodeArris, SyntheticExample) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + irsend.begin(); + irsend.reset(); + irsend.sendArris(0x1000085E); + irsend.makeDecodeResult(); + + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(decode_type_t::ARRIS, irsend.capture.decode_type); + EXPECT_EQ(kArrisBits, irsend.capture.bits); + EXPECT_EQ(0x1000085E, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x85, irsend.capture.command); + + EXPECT_EQ( + "f38000d50" +// const uint16_t rawData_1[59] = { +// 2584, 1896, + "m2560s1920" +// 666, 306, + "m640s320" +// 338, 300, + "m320s320" +// 336, 304, + "m320s320" +// 668, 610, + "m640s640" +// 332, 306, + "m320s320" +// 338, 300, + "m320s320" +// 334, 304, + "m320s320" +// 332, 312, + "m320s320" +// 332, 306, + "m320s320" +// 340, 300, + "m320s320" +// 334, 304, + "m320s320" +// 330, 308, + "m320s320" +// 338, 302, + "m320s320" +// 334, 304, + "m320s320" +// 330, 308, + "m320s320" +// 336, 308, + "m320s320" +// 336, 302, + "m320s320" +// 332, 306, + "m320s320" +// 330, 310, + "m320s320" +// 674, 606, + "m640s640" +// 336, 302, + "m320s320" +// 332, 306, + "m320s320" +// 338, 306, + "m320s320" +// 668, 612, + "m640s640" +// 668, 306, + "m640s320" +// 338, 304, + "m320s320" +// 332, 308, + "m320s320" +// 336, 608, + "m320s640" +// 334}; // UNKNOWN EDF1C0D0 + "m320s77184", irsend.outputStr()); + + irsend.reset(); + irsend.sendArris(0x1080695D); + irsend.makeDecodeResult(); + + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(decode_type_t::ARRIS, irsend.capture.decode_type); + EXPECT_EQ(kArrisBits, irsend.capture.bits); + EXPECT_EQ(0x1080695D, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); + EXPECT_EQ(0x695, irsend.capture.command); +} + +TEST(TestUtils, Housekeeping) { + ASSERT_EQ("ARRIS", typeToString(decode_type_t::ARRIS)); + ASSERT_EQ(decode_type_t::ARRIS, strToDecodeType("ARRIS")); + ASSERT_FALSE(hasACState(decode_type_t::ARRIS)); + ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::ARRIS)); + ASSERT_EQ(kArrisBits, IRsend::defaultBits(decode_type_t::ARRIS)); + ASSERT_EQ(kNoRepeat, IRsend::minRepeats(decode_type_t::ARRIS)); +} + +TEST(TestSendArris, ReleaseToggle) { + EXPECT_EQ(0x10800F5D, IRsend::toggleArrisRelease(0x10000F55)); + EXPECT_EQ(0x10000F55, IRsend::toggleArrisRelease(0x10800F5D)); + EXPECT_EQ( + 0x10800F5D, + IRsend::toggleArrisRelease(IRsend::toggleArrisRelease(0x10800F5D))); +} + +TEST(TestSendArris, encodeArris) { + EXPECT_EQ(0x10800F5D, IRsend::encodeArris(0xF5, true)); + EXPECT_EQ(0x10000F55, IRsend::encodeArris(0xF5, false)); + EXPECT_EQ(0x1080695D, IRsend::encodeArris(0x695, true)); +} diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Electra_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Electra_test.cpp index 1fddf537b..9c1dedd09 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Electra_test.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Electra_test.cpp @@ -101,7 +101,8 @@ TEST(TestDecodeElectraAC, RealExampleDecode) { EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); EXPECT_EQ( "Power: On, Mode: 1 (Cool), Temp: 24C, Fan: 3 (Low), " - "Swing(V): Off, Swing(H): Off, Light: -, Clean: Off, Turbo: Off", + "Swing(V): Off, Swing(H): Off, Light: -, Clean: Off, Turbo: Off, " + "IFeel: Off", IRAcUtils::resultAcToString(&irsend.capture)); stdAc::state_t r, p; ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &r, &p)); @@ -235,7 +236,8 @@ TEST(TestIRElectraAcClass, HumanReadable) { ac.setRaw(on_cool_32C_auto_voff); EXPECT_EQ( "Power: On, Mode: 1 (Cool), Temp: 32C, Fan: 5 (Auto), " - "Swing(V): Off, Swing(H): Off, Light: -, Clean: Off, Turbo: Off", + "Swing(V): Off, Swing(H): Off, Light: -, Clean: Off, Turbo: Off, " + "IFeel: Off", ac.toString()); uint8_t on_cool_16C_auto_voff[13] = { 0xC3, 0x47, 0xE0, 0x00, 0xA0, 0x00, 0x20, @@ -243,7 +245,8 @@ TEST(TestIRElectraAcClass, HumanReadable) { ac.setRaw(on_cool_16C_auto_voff); EXPECT_EQ( "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 5 (Auto), " - "Swing(V): Off, Swing(H): Off, Light: -, Clean: Off, Turbo: Off", + "Swing(V): Off, Swing(H): Off, Light: -, Clean: Off, Turbo: Off, " + "IFeel: Off", ac.toString()); uint8_t on_cool_16C_low_voff[13] = { 0xC3, 0x47, 0xE0, 0x00, 0x60, 0x00, 0x20, @@ -251,7 +254,8 @@ TEST(TestIRElectraAcClass, HumanReadable) { ac.setRaw(on_cool_16C_low_voff); EXPECT_EQ( "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 3 (Low), " - "Swing(V): Off, Swing(H): Off, Light: -, Clean: Off, Turbo: Off", + "Swing(V): Off, Swing(H): Off, Light: -, Clean: Off, Turbo: Off, " + "IFeel: Off", ac.toString()); } @@ -275,7 +279,8 @@ TEST(TestIRElectraAcClass, Clean) { ac.setRaw(on); EXPECT_EQ( "Power: On, Mode: 1 (Cool), Temp: 24C, Fan: 3 (Low), " - "Swing(V): Off, Swing(H): Off, Light: Toggle, Clean: On, Turbo: Off", + "Swing(V): Off, Swing(H): Off, Light: Toggle, Clean: On, Turbo: Off, " + "IFeel: Off", ac.toString()); } @@ -301,7 +306,8 @@ TEST(TestIRElectraAcClass, Turbo) { ac.setRaw(on); EXPECT_EQ( "Power: On, Mode: 1 (Cool), Temp: 24C, Fan: 3 (Low), " - "Swing(V): Off, Swing(H): Off, Light: -, Clean: Off, Turbo: On", + "Swing(V): Off, Swing(H): Off, Light: -, Clean: Off, Turbo: On, " + "IFeel: Off", ac.toString()); } @@ -325,7 +331,8 @@ TEST(TestIRElectraAcClass, LightToggle) { ac.setRaw(on); EXPECT_EQ( "Power: On, Mode: 1 (Cool), Temp: 24C, Fan: 3 (Low), " - "Swing(V): Off, Swing(H): Off, Light: Toggle, Clean: On, Turbo: Off", + "Swing(V): Off, Swing(H): Off, Light: Toggle, Clean: On, Turbo: Off, " + "IFeel: Off", ac.toString()); } @@ -352,8 +359,76 @@ TEST(TestIRElectraAcClass, ConstructKnownState) { EXPECT_EQ( "Power: On, Mode: 1 (Cool), Temp: 24C, Fan: 3 (Low), " - "Swing(V): Off, Swing(H): Off, Light: Toggle, Clean: On, Turbo: Off", + "Swing(V): Off, Swing(H): Off, Light: Toggle, Clean: On, Turbo: Off, " + "IFeel: Off", ac.toString()); EXPECT_STATE_EQ(on_cool_24C_fan1_swing_off_turbo_off_clean_on, ac.getRaw(), kElectraAcBits); } + +TEST(TestIRElectraAcClass, IFeelAndSensor) { + IRElectraAc ac(kGpioUnused); + ac.stateReset(); + // Test a real example. + const uint8_t ifeel_on[kElectraAcStateLength] = { + 0xC3, 0x6F, 0xE0, 0x00, 0xA0, 0x00, 0x28, + 0x64, 0x00, 0x20, 0x00, 0x1E, 0x7C}; + ac.setRaw(ifeel_on); + EXPECT_TRUE(ac.getIFeel()); + EXPECT_EQ(26, ac.getSensorTemp()); + EXPECT_EQ( + "Power: On, Mode: 1 (Cool), Temp: 21C, Fan: 5 (Auto), " + "Swing(V): Off, Swing(H): Off, Light: -, Clean: Off, Turbo: Off, " + "IFeel: On, Sensor Temp: 26C", + ac.toString()); + + ac.stateReset(); + EXPECT_FALSE(ac.getIFeel()); + EXPECT_EQ(kElectraAcSensorMinTemp, ac.getSensorTemp()); + + ac.setIFeel(true); + EXPECT_TRUE(ac.getIFeel()); + EXPECT_EQ(kElectraAcSensorMinTemp, ac.getSensorTemp()); + + ac.setSensorTemp(kElectraAcSensorMaxTemp); + EXPECT_EQ(kElectraAcSensorMaxTemp, ac.getSensorTemp()); + + ac.setSensorTemp(kElectraAcSensorMaxTemp + 1); + EXPECT_EQ(kElectraAcSensorMaxTemp, ac.getSensorTemp()); + + ac.setIFeel(false); + EXPECT_FALSE(ac.getIFeel()); + EXPECT_EQ(kElectraAcSensorMinTemp, ac.getSensorTemp()); + EXPECT_EQ(0, ac._.SensorTemp); + + ac.setIFeel(true); + ac.setSensorTemp(kElectraAcSensorMinTemp); + EXPECT_TRUE(ac.getIFeel()); + EXPECT_EQ(kElectraAcSensorMinTemp, ac.getSensorTemp()); + + ac.setSensorTemp(26); // Celsius + EXPECT_TRUE(ac.getIFeel()); + EXPECT_EQ(26, ac.getSensorTemp()); + + EXPECT_FALSE(ac.getSensorUpdate()); + ac.setSensorUpdate(true); + EXPECT_TRUE(ac.getSensorUpdate()); + EXPECT_EQ("Sensor Temp: 26C", ac.toString()); + ac.setSensorUpdate(false); + EXPECT_FALSE(ac.getSensorUpdate()); + + const uint8_t sensor_update_28C[kElectraAcStateLength] = { + 0xC3, 0x9F, 0xE0, 0x40, 0xA0, 0x00, 0x88, + 0x66, 0x00, 0x30, 0x00, 0x1E, 0x5E}; + ac.setRaw(sensor_update_28C); + EXPECT_TRUE(ac.getSensorUpdate()); + EXPECT_EQ(28, ac.getSensorTemp()); + EXPECT_EQ("Sensor Temp: 28C", ac.toString()); + ac.setSensorUpdate(false); + EXPECT_FALSE(ac.getSensorUpdate()); + EXPECT_EQ( + "Power: On, Mode: 4 (Heat), Temp: 27C, Fan: 5 (Auto), " + "Swing(V): Off, Swing(H): Off, Light: -, Clean: Off, Turbo: Off, " + "IFeel: On, Sensor Temp: 28C", + ac.toString()); +} diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Gree_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Gree_test.cpp index 597fd3c09..cb1832f61 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Gree_test.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Gree_test.cpp @@ -303,9 +303,10 @@ TEST(TestGreeClass, Temperature) { EXPECT_EQ(63, ac.getTemp()); EXPECT_EQ( "Model: 2 (YBOFB), Power: On, Mode: 1 (Cool), Temp: 63F, Fan: 0 (Auto), " - "Turbo: Off, IFeel: Off, WiFi: Off, XFan: Off, Light: On, Sleep: Off, " - "Swing(V) Mode: Manual, Swing(V): 0 (Last), Timer: Off, " - "Display Temp: 0 (Off)", ac.toString()); + "Turbo: Off, Econo: Off, IFeel: Off, WiFi: Off, XFan: Off, Light: On, " + "Sleep: Off, " + "Swing(V) Mode: Manual, Swing(V): 0 (Last), Swing(H): 0 (Off), " + "Timer: Off, Display Temp: 0 (Off)", ac.toString()); } TEST(TestGreeClass, OperatingMode) { @@ -385,6 +386,20 @@ TEST(TestGreeClass, Turbo) { EXPECT_TRUE(ac.getTurbo()); } +TEST(TestGreeClass, Econo) { + IRGreeAC ac(kGpioUnused); + ac.begin(); + + ac.setEcono(true); + EXPECT_TRUE(ac.getEcono()); + + ac.setEcono(false); + EXPECT_FALSE(ac.getEcono()); + + ac.setEcono(true); + EXPECT_TRUE(ac.getEcono()); +} + TEST(TestGreeClass, IFeel) { IRGreeAC ac(kGpioUnused); ac.begin(); @@ -506,6 +521,24 @@ TEST(TestGreeClass, VerticalSwing) { EXPECT_EQ(kGreeSwingAuto, ac.getSwingVerticalPosition()); } +TEST(TestGreeClass, HorizontalSwing) { + IRGreeAC ac(kGpioUnused); + ac.begin(); + + ac.setSwingHorizontal(kGreeSwingHAuto); + EXPECT_EQ(kGreeSwingHAuto, ac.getSwingHorizontal()); + + ac.setSwingHorizontal(kGreeSwingHMiddle); + EXPECT_EQ(kGreeSwingHMiddle, ac.getSwingHorizontal()); + + ac.setSwingHorizontal(kGreeSwingHMaxRight); + EXPECT_EQ(kGreeSwingHMaxRight, ac.getSwingHorizontal()); + + // Out of bounds. + ac.setSwingHorizontal(kGreeSwingHMaxRight + 1); + EXPECT_EQ(kGreeSwingHOff, ac.getSwingHorizontal()); +} + TEST(TestGreeClass, SetAndGetRaw) { IRGreeAC ac(kGpioUnused); uint8_t initialState[kGreeStateLength] = {0x00, 0x09, 0x20, 0x50, @@ -543,8 +576,9 @@ TEST(TestGreeClass, HumanReadable) { EXPECT_EQ( "Model: 1 (YAW1F), Power: Off, Mode: 0 (Auto), Temp: 25C, Fan: 0 (Auto), " - "Turbo: Off, IFeel: Off, WiFi: Off, XFan: Off, Light: On, Sleep: Off, " - "Swing(V) Mode: Manual, Swing(V): 0 (Last), " + "Turbo: Off, Econo: Off, IFeel: Off, WiFi: Off, XFan: Off, Light: On, " + "Sleep: Off, " + "Swing(V) Mode: Manual, Swing(V): 0 (Last), Swing(H): 0 (Off), " "Timer: Off, Display Temp: 0 (Off)", ac.toString()); ac.on(); @@ -562,9 +596,10 @@ TEST(TestGreeClass, HumanReadable) { ac.setDisplayTempSource(3); EXPECT_EQ( "Model: 1 (YAW1F), Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 3 (High), " - "Turbo: On, IFeel: On, WiFi: On, XFan: On, Light: Off, Sleep: On, " - "Swing(V) Mode: Auto, Swing(V): 1 (Auto), Timer: 12:30, " - "Display Temp: 3 (Outside)", + "Turbo: On, Econo: Off, IFeel: On, WiFi: On, XFan: On, Light: Off, " + "Sleep: On, " + "Swing(V) Mode: Auto, Swing(V): 1 (Auto), Swing(H): 0 (Off), " + "Timer: 12:30, Display Temp: 3 (Outside)", ac.toString()); } @@ -623,9 +658,10 @@ TEST(TestDecodeGree, NormalRealExample) { ac.setRaw(irsend.capture.state); EXPECT_EQ( "Model: 1 (YAW1F), Power: On, Mode: 1 (Cool), Temp: 26C, Fan: 1 (Low), " - "Turbo: Off, IFeel: Off, WiFi: Off, XFan: Off, Light: On, Sleep: Off, " - "Swing(V) Mode: Manual, Swing(V): 2 (UNKNOWN), Timer: Off, " - "Display Temp: 3 (Outside)", + "Turbo: Off, Econo: Off, IFeel: Off, WiFi: Off, XFan: Off, Light: On, " + "Sleep: Off, " + "Swing(V) Mode: Manual, Swing(V): 2 (UNKNOWN), Swing(H): 0 (Off), " + "Timer: Off, Display Temp: 3 (Outside)", IRAcUtils::resultAcToString(&irsend.capture)); stdAc::state_t r, p; ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &r, &p)); @@ -681,8 +717,9 @@ TEST(TestGreeClass, Issue814Power) { EXPECT_EQ(gree_ac_remote_model_t::YBOFB, ac.getModel()); EXPECT_EQ( "Model: 2 (YBOFB), Power: On, Mode: 1 (Cool), Temp: 23C, Fan: 1 (Low), " - "Turbo: Off, IFeel: Off, WiFi: Off, XFan: Off, Light: On, Sleep: Off, " - "Swing(V) Mode: Auto, Swing(V): 1 (Auto), Timer: Off, " + "Turbo: Off, Econo: Off, IFeel: Off, WiFi: Off, XFan: Off, Light: On, " + "Sleep: Off, " + "Swing(V) Mode: Auto, Swing(V): 1 (Auto), Swing(H): 0 (Off), Timer: Off, " "Display Temp: 0 (Off)", ac.toString()); ac.off(); diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Haier_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Haier_test.cpp index 8b89b1098..b60a08f23 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Haier_test.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Haier_test.cpp @@ -105,597 +105,711 @@ TEST(TestSendHaierAC, SendWithRepeats) { // Tests for IRHaierAC class. TEST(TestHaierACClass, Command) { - IRHaierAC haier(kGpioUnused); - haier.begin(); + IRHaierAC ac(kGpioUnused); + ac.begin(); - haier.setCommand(kHaierAcCmdOff); - EXPECT_EQ(kHaierAcCmdOff, haier.getCommand()); - haier.setCommand(kHaierAcCmdOn); - EXPECT_EQ(kHaierAcCmdOn, haier.getCommand()); - haier.setCommand(kHaierAcCmdMode); - EXPECT_EQ(kHaierAcCmdMode, haier.getCommand()); - haier.setCommand(kHaierAcCmdFan); - EXPECT_EQ(kHaierAcCmdFan, haier.getCommand()); - haier.setCommand(kHaierAcCmdTempUp); - EXPECT_EQ(kHaierAcCmdTempUp, haier.getCommand()); - haier.setCommand(kHaierAcCmdTempDown); - EXPECT_EQ(kHaierAcCmdTempDown, haier.getCommand()); - haier.setCommand(kHaierAcCmdSleep); - EXPECT_EQ(kHaierAcCmdSleep, haier.getCommand()); - haier.setCommand(kHaierAcCmdTimerSet); - EXPECT_EQ(kHaierAcCmdTimerSet, haier.getCommand()); - haier.setCommand(kHaierAcCmdTimerCancel); - EXPECT_EQ(kHaierAcCmdTimerCancel, haier.getCommand()); - haier.setCommand(kHaierAcCmdHealth); - EXPECT_EQ(kHaierAcCmdHealth, haier.getCommand()); - haier.setCommand(kHaierAcCmdSwing); - EXPECT_EQ(kHaierAcCmdSwing, haier.getCommand()); - haier.setCommand(kHaierAcCmdOn); - EXPECT_EQ(kHaierAcCmdOn, haier.getCommand()); - haier.setCommand(kHaierAcCmdOff); - EXPECT_EQ(kHaierAcCmdOff, haier.getCommand()); + ac.setCommand(kHaierAcCmdOff); + EXPECT_EQ(kHaierAcCmdOff, ac.getCommand()); + ac.setCommand(kHaierAcCmdOn); + EXPECT_EQ(kHaierAcCmdOn, ac.getCommand()); + ac.setCommand(kHaierAcCmdMode); + EXPECT_EQ(kHaierAcCmdMode, ac.getCommand()); + ac.setCommand(kHaierAcCmdFan); + EXPECT_EQ(kHaierAcCmdFan, ac.getCommand()); + ac.setCommand(kHaierAcCmdTempUp); + EXPECT_EQ(kHaierAcCmdTempUp, ac.getCommand()); + ac.setCommand(kHaierAcCmdTempDown); + EXPECT_EQ(kHaierAcCmdTempDown, ac.getCommand()); + ac.setCommand(kHaierAcCmdSleep); + EXPECT_EQ(kHaierAcCmdSleep, ac.getCommand()); + ac.setCommand(kHaierAcCmdTimerSet); + EXPECT_EQ(kHaierAcCmdTimerSet, ac.getCommand()); + ac.setCommand(kHaierAcCmdTimerCancel); + EXPECT_EQ(kHaierAcCmdTimerCancel, ac.getCommand()); + ac.setCommand(kHaierAcCmdHealth); + EXPECT_EQ(kHaierAcCmdHealth, ac.getCommand()); + ac.setCommand(kHaierAcCmdSwing); + EXPECT_EQ(kHaierAcCmdSwing, ac.getCommand()); + ac.setCommand(kHaierAcCmdOn); + EXPECT_EQ(kHaierAcCmdOn, ac.getCommand()); + ac.setCommand(kHaierAcCmdOff); + EXPECT_EQ(kHaierAcCmdOff, ac.getCommand()); // Test unexpected values. - haier.setCommand(0b00001110); - EXPECT_EQ(kHaierAcCmdOff, haier.getCommand()); - haier.setCommand(0b00001111); - EXPECT_EQ(kHaierAcCmdOff, haier.getCommand()); - haier.setCommand(0b00000100); - EXPECT_EQ(kHaierAcCmdOff, haier.getCommand()); + ac.setCommand(0b00001110); + EXPECT_EQ(kHaierAcCmdOff, ac.getCommand()); + ac.setCommand(0b00001111); + EXPECT_EQ(kHaierAcCmdOff, ac.getCommand()); + ac.setCommand(0b00000100); + EXPECT_EQ(kHaierAcCmdOff, ac.getCommand()); } TEST(TestHaierACClass, OperatingMode) { - IRHaierAC haier(kGpioUnused); - haier.begin(); + IRHaierAC ac(kGpioUnused); + ac.begin(); - haier.setMode(kHaierAcAuto); - EXPECT_EQ(kHaierAcAuto, haier.getMode()); + ac.setMode(kHaierAcAuto); + EXPECT_EQ(kHaierAcAuto, ac.getMode()); - haier.setMode(kHaierAcCool); - EXPECT_EQ(kHaierAcCool, haier.getMode()); + ac.setMode(kHaierAcCool); + EXPECT_EQ(kHaierAcCool, ac.getMode()); - haier.setMode(kHaierAcHeat); - EXPECT_EQ(kHaierAcHeat, haier.getMode()); + ac.setMode(kHaierAcHeat); + EXPECT_EQ(kHaierAcHeat, ac.getMode()); - haier.setMode(kHaierAcFan); - EXPECT_EQ(kHaierAcFan, haier.getMode()); + ac.setMode(kHaierAcFan); + EXPECT_EQ(kHaierAcFan, ac.getMode()); - haier.setMode(kHaierAcDry); - EXPECT_EQ(kHaierAcDry, haier.getMode()); + ac.setMode(kHaierAcDry); + EXPECT_EQ(kHaierAcDry, ac.getMode()); - haier.setMode(kHaierAcAuto - 1); - EXPECT_EQ(kHaierAcAuto, haier.getMode()); + ac.setMode(kHaierAcAuto - 1); + EXPECT_EQ(kHaierAcAuto, ac.getMode()); - haier.setMode(kHaierAcCool); - EXPECT_EQ(kHaierAcCool, haier.getMode()); + ac.setMode(kHaierAcCool); + EXPECT_EQ(kHaierAcCool, ac.getMode()); - haier.setMode(kHaierAcFan + 1); - EXPECT_EQ(kHaierAcAuto, haier.getMode()); + ac.setMode(kHaierAcFan + 1); + EXPECT_EQ(kHaierAcAuto, ac.getMode()); - haier.setMode(255); - EXPECT_EQ(kHaierAcAuto, haier.getMode()); + ac.setMode(255); + EXPECT_EQ(kHaierAcAuto, ac.getMode()); } TEST(TestHaierACClass, Temperature) { - IRHaierAC haier(kGpioUnused); - haier.begin(); + IRHaierAC ac(kGpioUnused); + ac.begin(); - haier.setTemp(kHaierAcMinTemp); - EXPECT_EQ(kHaierAcMinTemp, haier.getTemp()); + ac.setTemp(kHaierAcMinTemp); + EXPECT_EQ(kHaierAcMinTemp, ac.getTemp()); - haier.setCommand(kHaierAcCmdOn); - haier.setTemp(kHaierAcMinTemp + 1); - EXPECT_EQ(kHaierAcMinTemp + 1, haier.getTemp()); - EXPECT_EQ(kHaierAcCmdTempUp, haier.getCommand()); + ac.setCommand(kHaierAcCmdOn); + ac.setTemp(kHaierAcMinTemp + 1); + EXPECT_EQ(kHaierAcMinTemp + 1, ac.getTemp()); + EXPECT_EQ(kHaierAcCmdTempUp, ac.getCommand()); - haier.setTemp(kHaierAcMaxTemp); - EXPECT_EQ(kHaierAcMaxTemp, haier.getTemp()); - EXPECT_EQ(kHaierAcCmdTempUp, haier.getCommand()); + ac.setTemp(kHaierAcMaxTemp); + EXPECT_EQ(kHaierAcMaxTemp, ac.getTemp()); + EXPECT_EQ(kHaierAcCmdTempUp, ac.getCommand()); - haier.setTemp(kHaierAcMinTemp - 1); - EXPECT_EQ(kHaierAcMinTemp, haier.getTemp()); - EXPECT_EQ(kHaierAcCmdTempDown, haier.getCommand()); + ac.setTemp(kHaierAcMinTemp - 1); + EXPECT_EQ(kHaierAcMinTemp, ac.getTemp()); + EXPECT_EQ(kHaierAcCmdTempDown, ac.getCommand()); - haier.setTemp(kHaierAcMaxTemp + 1); - EXPECT_EQ(kHaierAcMaxTemp, haier.getTemp()); - EXPECT_EQ(kHaierAcCmdTempUp, haier.getCommand()); + ac.setTemp(kHaierAcMaxTemp + 1); + EXPECT_EQ(kHaierAcMaxTemp, ac.getTemp()); + EXPECT_EQ(kHaierAcCmdTempUp, ac.getCommand()); - haier.setTemp(23); - EXPECT_EQ(23, haier.getTemp()); - EXPECT_EQ(kHaierAcCmdTempDown, haier.getCommand()); - haier.setCommand(kHaierAcCmdOn); - haier.setTemp(23); - EXPECT_EQ(23, haier.getTemp()); - EXPECT_EQ(kHaierAcCmdOn, haier.getCommand()); + ac.setTemp(23); + EXPECT_EQ(23, ac.getTemp()); + EXPECT_EQ(kHaierAcCmdTempDown, ac.getCommand()); + ac.setCommand(kHaierAcCmdOn); + ac.setTemp(23); + EXPECT_EQ(23, ac.getTemp()); + EXPECT_EQ(kHaierAcCmdOn, ac.getCommand()); - haier.setTemp(0); - EXPECT_EQ(kHaierAcMinTemp, haier.getTemp()); - EXPECT_EQ(kHaierAcCmdTempDown, haier.getCommand()); + ac.setTemp(0); + EXPECT_EQ(kHaierAcMinTemp, ac.getTemp()); + EXPECT_EQ(kHaierAcCmdTempDown, ac.getCommand()); - haier.setTemp(255); - EXPECT_EQ(kHaierAcMaxTemp, haier.getTemp()); - EXPECT_EQ(kHaierAcCmdTempUp, haier.getCommand()); + ac.setTemp(255); + EXPECT_EQ(kHaierAcMaxTemp, ac.getTemp()); + EXPECT_EQ(kHaierAcCmdTempUp, ac.getCommand()); } TEST(TestHaierACClass, FanSpeed) { - IRHaierAC haier(kGpioUnused); - haier.begin(); - haier.setFan(kHaierAcFanLow); - haier.setCommand(kHaierAcCmdOn); + IRHaierAC ac(kGpioUnused); + ac.begin(); + ac.setFan(kHaierAcFanLow); + ac.setCommand(kHaierAcCmdOn); - haier.setFan(kHaierAcFanAuto); - EXPECT_EQ(kHaierAcFanAuto, haier.getFan()); - EXPECT_EQ(kHaierAcCmdFan, haier.getCommand()); + ac.setFan(kHaierAcFanAuto); + EXPECT_EQ(kHaierAcFanAuto, ac.getFan()); + EXPECT_EQ(kHaierAcCmdFan, ac.getCommand()); - haier.setFan(kHaierAcFanLow); - EXPECT_EQ(kHaierAcFanLow, haier.getFan()); - haier.setFan(kHaierAcFanMed); - EXPECT_EQ(kHaierAcFanMed, haier.getFan()); - haier.setFan(kHaierAcFanHigh); - EXPECT_EQ(kHaierAcFanHigh, haier.getFan()); + ac.setFan(kHaierAcFanLow); + EXPECT_EQ(kHaierAcFanLow, ac.getFan()); + ac.setFan(kHaierAcFanMed); + EXPECT_EQ(kHaierAcFanMed, ac.getFan()); + ac.setFan(kHaierAcFanHigh); + EXPECT_EQ(kHaierAcFanHigh, ac.getFan()); - haier.setCommand(kHaierAcCmdOn); - haier.setFan(kHaierAcFanHigh); - EXPECT_EQ(kHaierAcFanHigh, haier.getFan()); - EXPECT_EQ(kHaierAcCmdOn, haier.getCommand()); + ac.setCommand(kHaierAcCmdOn); + ac.setFan(kHaierAcFanHigh); + EXPECT_EQ(kHaierAcFanHigh, ac.getFan()); + EXPECT_EQ(kHaierAcCmdOn, ac.getCommand()); } -TEST(TestHaierACClass, Swing) { - IRHaierAC haier(kGpioUnused); - haier.begin(); - haier.setFan(kHaierAcFanLow); - haier.setCommand(kHaierAcCmdOn); +TEST(TestHaierACClass, SwingV) { + IRHaierAC ac(kGpioUnused); + ac.begin(); + ac.setFan(kHaierAcFanLow); + ac.setCommand(kHaierAcCmdOn); - haier.setSwing(kHaierAcSwingOff); - EXPECT_EQ(kHaierAcSwingOff, haier.getSwing()); + ac.setSwingV(kHaierAcSwingVOff); + EXPECT_EQ(kHaierAcSwingVOff, ac.getSwingV()); - haier.setSwing(kHaierAcSwingUp); - EXPECT_EQ(kHaierAcSwingUp, haier.getSwing()); - EXPECT_EQ(kHaierAcCmdSwing, haier.getCommand()); + ac.setSwingV(kHaierAcSwingVUp); + EXPECT_EQ(kHaierAcSwingVUp, ac.getSwingV()); + EXPECT_EQ(kHaierAcCmdSwing, ac.getCommand()); - haier.setSwing(kHaierAcSwingDown); - EXPECT_EQ(kHaierAcSwingDown, haier.getSwing()); - EXPECT_EQ(kHaierAcCmdSwing, haier.getCommand()); + ac.setSwingV(kHaierAcSwingVDown); + EXPECT_EQ(kHaierAcSwingVDown, ac.getSwingV()); + EXPECT_EQ(kHaierAcCmdSwing, ac.getCommand()); - haier.setSwing(kHaierAcSwingChg); - EXPECT_EQ(kHaierAcSwingChg, haier.getSwing()); - EXPECT_EQ(kHaierAcCmdSwing, haier.getCommand()); + ac.setSwingV(kHaierAcSwingVChg); + EXPECT_EQ(kHaierAcSwingVChg, ac.getSwingV()); + EXPECT_EQ(kHaierAcCmdSwing, ac.getCommand()); } TEST(TestHaierACClass, CurrentTime) { - IRHaierAC haier(kGpioUnused); - haier.begin(); - EXPECT_EQ(0, haier.getCurrTime()); + IRHaierAC ac(kGpioUnused); + ac.begin(); + EXPECT_EQ(0, ac.getCurrTime()); - haier.setCurrTime(1); - EXPECT_EQ(1, haier.getCurrTime()); + ac.setCurrTime(1); + EXPECT_EQ(1, ac.getCurrTime()); - haier.setCurrTime(60); - EXPECT_EQ(60, haier.getCurrTime()); + ac.setCurrTime(60); + EXPECT_EQ(60, ac.getCurrTime()); - haier.setCurrTime(61); - EXPECT_EQ(61, haier.getCurrTime()); + ac.setCurrTime(61); + EXPECT_EQ(61, ac.getCurrTime()); - haier.setCurrTime(18 * 60 + 34); // 18:34 - EXPECT_EQ(1114, haier.getCurrTime()); + ac.setCurrTime(18 * 60 + 34); // 18:34 + EXPECT_EQ(1114, ac.getCurrTime()); - haier.setCurrTime(23 * 60 + 59); // 23:59 - EXPECT_EQ(kHaierAcMaxTime, haier.getCurrTime()); // 23:59 + ac.setCurrTime(23 * 60 + 59); // 23:59 + EXPECT_EQ(kHaierAcMaxTime, ac.getCurrTime()); // 23:59 - haier.setCurrTime(23 * 60 + 59 + 1); // 24:00 - EXPECT_EQ(kHaierAcMaxTime, haier.getCurrTime()); // 23:59 + ac.setCurrTime(23 * 60 + 59 + 1); // 24:00 + EXPECT_EQ(kHaierAcMaxTime, ac.getCurrTime()); // 23:59 - haier.setCurrTime(UINT16_MAX); - EXPECT_EQ(kHaierAcMaxTime, haier.getCurrTime()); // 23:59 + ac.setCurrTime(UINT16_MAX); + EXPECT_EQ(kHaierAcMaxTime, ac.getCurrTime()); // 23:59 } TEST(TestHaierACClass, Timers) { - IRHaierAC haier(kGpioUnused); - haier.begin(); + IRHaierAC ac(kGpioUnused); + ac.begin(); - haier.setCommand(kHaierAcCmdOn); + ac.setCommand(kHaierAcCmdOn); // Off by default. - EXPECT_GT(0, haier.getOnTimer()); - EXPECT_GT(0, haier.getOffTimer()); - EXPECT_EQ(kHaierAcCmdOn, haier.getCommand()); + EXPECT_GT(0, ac.getOnTimer()); + EXPECT_GT(0, ac.getOffTimer()); + EXPECT_EQ(kHaierAcCmdOn, ac.getCommand()); // On Timer. - haier.setOnTimer(6 * 60); // 6am - EXPECT_EQ(6 * 60, haier.getOnTimer()); // 6am - EXPECT_GT(0, haier.getOffTimer()); - EXPECT_EQ(kHaierAcCmdTimerSet, haier.getCommand()); + ac.setOnTimer(6 * 60); // 6am + EXPECT_EQ(6 * 60, ac.getOnTimer()); // 6am + EXPECT_GT(0, ac.getOffTimer()); + EXPECT_EQ(kHaierAcCmdTimerSet, ac.getCommand()); - haier.setCommand(kHaierAcCmdOn); - EXPECT_EQ(6 * 60, haier.getOnTimer()); // 6am - EXPECT_GT(0, haier.getOffTimer()); - EXPECT_EQ(kHaierAcCmdOn, haier.getCommand()); + ac.setCommand(kHaierAcCmdOn); + EXPECT_EQ(6 * 60, ac.getOnTimer()); // 6am + EXPECT_GT(0, ac.getOffTimer()); + EXPECT_EQ(kHaierAcCmdOn, ac.getCommand()); - haier.cancelTimers(); - EXPECT_GT(0, haier.getOnTimer()); - EXPECT_GT(0, haier.getOffTimer()); - EXPECT_EQ(kHaierAcCmdTimerCancel, haier.getCommand()); + ac.cancelTimers(); + EXPECT_GT(0, ac.getOnTimer()); + EXPECT_GT(0, ac.getOffTimer()); + EXPECT_EQ(kHaierAcCmdTimerCancel, ac.getCommand()); // Off Timer. - haier.setOffTimer(18 * 60 + 30); // 6:30pm - EXPECT_GT(0, haier.getOnTimer()); - EXPECT_EQ(18 * 60 + 30, haier.getOffTimer()); // 6:30pm - EXPECT_EQ(kHaierAcCmdTimerSet, haier.getCommand()); + ac.setOffTimer(18 * 60 + 30); // 6:30pm + EXPECT_GT(0, ac.getOnTimer()); + EXPECT_EQ(18 * 60 + 30, ac.getOffTimer()); // 6:30pm + EXPECT_EQ(kHaierAcCmdTimerSet, ac.getCommand()); - haier.setCommand(kHaierAcCmdOn); - EXPECT_GT(0, haier.getOnTimer()); - EXPECT_EQ(18 * 60 + 30, haier.getOffTimer()); // 6:30pm - EXPECT_EQ(kHaierAcCmdOn, haier.getCommand()); + ac.setCommand(kHaierAcCmdOn); + EXPECT_GT(0, ac.getOnTimer()); + EXPECT_EQ(18 * 60 + 30, ac.getOffTimer()); // 6:30pm + EXPECT_EQ(kHaierAcCmdOn, ac.getCommand()); - haier.cancelTimers(); - EXPECT_GT(0, haier.getOnTimer()); - EXPECT_GT(0, haier.getOffTimer()); - EXPECT_EQ(kHaierAcCmdTimerCancel, haier.getCommand()); + ac.cancelTimers(); + EXPECT_GT(0, ac.getOnTimer()); + EXPECT_GT(0, ac.getOffTimer()); + EXPECT_EQ(kHaierAcCmdTimerCancel, ac.getCommand()); // Both Timers. - haier.setOnTimer(6 * 60); // 6am - EXPECT_EQ(kHaierAcCmdTimerSet, haier.getCommand()); - haier.setOffTimer(18 * 60 + 30); // 6:30pm - EXPECT_EQ(kHaierAcCmdTimerSet, haier.getCommand()); - EXPECT_EQ(6 * 60, haier.getOnTimer()); // 6am - EXPECT_EQ(18 * 60 + 30, haier.getOffTimer()); // 6:30pm + ac.setOnTimer(6 * 60); // 6am + EXPECT_EQ(kHaierAcCmdTimerSet, ac.getCommand()); + ac.setOffTimer(18 * 60 + 30); // 6:30pm + EXPECT_EQ(kHaierAcCmdTimerSet, ac.getCommand()); + EXPECT_EQ(6 * 60, ac.getOnTimer()); // 6am + EXPECT_EQ(18 * 60 + 30, ac.getOffTimer()); // 6:30pm - haier.cancelTimers(); - EXPECT_GT(0, haier.getOnTimer()); - EXPECT_GT(0, haier.getOffTimer()); - EXPECT_EQ(kHaierAcCmdTimerCancel, haier.getCommand()); + ac.cancelTimers(); + EXPECT_GT(0, ac.getOnTimer()); + EXPECT_GT(0, ac.getOffTimer()); + EXPECT_EQ(kHaierAcCmdTimerCancel, ac.getCommand()); } TEST(TestHaierACClass, MessageConstuction) { - IRHaierAC haier(kGpioUnused); + IRHaierAC ac(kGpioUnused); EXPECT_EQ( "Command: 1 (On), Mode: 0 (Auto), Temp: 25C, Fan: 1 (Low), " - "Swing: 0 (Off), Sleep: Off, Health: Off, " + "Swing(V): 0 (Off), Sleep: Off, Health: Off, " "Clock: 00:00, On Timer: Off, Off Timer: Off", - haier.toString()); - haier.setMode(kHaierAcCool); - haier.setTemp(21); - haier.setFan(kHaierAcFanHigh); + ac.toString()); + ac.setMode(kHaierAcCool); + ac.setTemp(21); + ac.setFan(kHaierAcFanHigh); EXPECT_EQ( "Command: 3 (Fan), Mode: 1 (Cool), Temp: 21C, Fan: 3 (High), " - "Swing: 0 (Off), Sleep: Off, Health: Off, " + "Swing(V): 0 (Off), Sleep: Off, Health: Off, " "Clock: 00:00, On Timer: Off, Off Timer: Off", - haier.toString()); - haier.setSwing(kHaierAcSwingChg); - haier.setHealth(true); - haier.setSleep(true); - haier.setCurrTime(615); // 10:15am + ac.toString()); + ac.setSwingV(kHaierAcSwingVChg); + ac.setHealth(true); + ac.setSleep(true); + ac.setCurrTime(615); // 10:15am EXPECT_EQ( "Command: 8 (Sleep), Mode: 1 (Cool), Temp: 21C, Fan: 3 (High), " - "Swing: 3 (Change), Sleep: On, Health: On, " + "Swing(V): 3 (Change), Sleep: On, Health: On, " "Clock: 10:15, On Timer: Off, Off Timer: Off", - haier.toString()); - haier.setOnTimer(800); // 1:20pm - haier.setOffTimer(1125); // 6:45pm - haier.setCommand(kHaierAcCmdOn); + ac.toString()); + ac.setOnTimer(800); // 1:20pm + ac.setOffTimer(1125); // 6:45pm + ac.setCommand(kHaierAcCmdOn); EXPECT_EQ( "Command: 1 (On), Mode: 1 (Cool), Temp: 21C, Fan: 3 (High), " - "Swing: 3 (Change), Sleep: On, Health: On, " + "Swing(V): 3 (Change), Sleep: On, Health: On, " "Clock: 10:15, On Timer: 13:20, Off Timer: 18:45", - haier.toString()); + ac.toString()); // Now change a few already set things. - haier.setMode(kHaierAcHeat); + ac.setMode(kHaierAcHeat); EXPECT_EQ( "Command: 2 (Mode), Mode: 3 (Heat), Temp: 21C, Fan: 3 (High), " - "Swing: 3 (Change), Sleep: On, Health: On, " + "Swing(V): 3 (Change), Sleep: On, Health: On, " "Clock: 10:15, On Timer: 13:20, Off Timer: 18:45", - haier.toString()); + ac.toString()); - haier.setTemp(25); + ac.setTemp(25); EXPECT_EQ( "Command: 6 (Temp Up), Mode: 3 (Heat), Temp: 25C, Fan: 3 (High), " - "Swing: 3 (Change), Sleep: On, Health: On, " + "Swing(V): 3 (Change), Sleep: On, Health: On, " "Clock: 10:15, On Timer: 13:20, Off Timer: 18:45", - haier.toString()); + ac.toString()); uint8_t expectedState[kHaierACStateLength] = {0xA5, 0x96, 0xEA, 0xCF, 0x32, 0x6D, 0x6D, 0x54, 0x54}; - EXPECT_STATE_EQ(expectedState, haier.getRaw(), kHaierACBits); + EXPECT_STATE_EQ(expectedState, ac.getRaw(), kHaierACBits); // Check that the checksum is valid. - EXPECT_TRUE(IRHaierAC::validChecksum(haier.getRaw())); + EXPECT_TRUE(IRHaierAC::validChecksum(ac.getRaw())); // Now load up some random data. uint8_t randomState[kHaierACStateLength] = {0x52, 0x49, 0x50, 0x20, 0x54, 0x61, 0x6C, 0x69, 0x61}; EXPECT_FALSE(IRHaierAC::validChecksum(randomState)); - haier.setRaw(randomState); + ac.setRaw(randomState); EXPECT_EQ( "Command: 9 (Timer Set), Mode: 3 (Heat), Temp: 20C, Fan: 3 (High), " - "Swing: 1 (Up), Sleep: On, Health: Off, " + "Swing(V): 1 (Up), Sleep: On, Health: Off, " "Clock: 16:32, On Timer: Off, Off Timer: Off", - haier.toString()); + ac.toString()); // getRaw() should correct the checksum. - EXPECT_TRUE(IRHaierAC::validChecksum(haier.getRaw())); + EXPECT_TRUE(IRHaierAC::validChecksum(ac.getRaw())); } // Tests for the IRHaierACYRW02 class. TEST(TestHaierACYRW02Class, Button) { - IRHaierACYRW02 haier(kGpioUnused); - haier.begin(); + IRHaierACYRW02 ac(kGpioUnused); + ac.begin(); - haier.setButton(kHaierAcYrw02ButtonPower); - EXPECT_EQ(kHaierAcYrw02ButtonPower, haier.getButton()); - haier.setButton(kHaierAcYrw02ButtonMode); - EXPECT_EQ(kHaierAcYrw02ButtonMode, haier.getButton()); - haier.setButton(kHaierAcYrw02ButtonSleep); - EXPECT_EQ(kHaierAcYrw02ButtonSleep, haier.getButton()); - haier.setButton(kHaierAcYrw02ButtonFan); + ac.setButton(kHaierAcYrw02ButtonPower); + EXPECT_EQ(kHaierAcYrw02ButtonPower, ac.getButton()); + ac.setButton(kHaierAcYrw02ButtonMode); + EXPECT_EQ(kHaierAcYrw02ButtonMode, ac.getButton()); + ac.setButton(kHaierAcYrw02ButtonSleep); + EXPECT_EQ(kHaierAcYrw02ButtonSleep, ac.getButton()); + ac.setButton(kHaierAcYrw02ButtonFan); // Test unexpected values. - haier.setButton(0xFF); - EXPECT_EQ(kHaierAcYrw02ButtonFan, haier.getButton()); - haier.setButton(0x10); - EXPECT_EQ(kHaierAcYrw02ButtonFan, haier.getButton()); + ac.setButton(0xFF); + EXPECT_EQ(kHaierAcYrw02ButtonFan, ac.getButton()); + ac.setButton(0x10); + EXPECT_EQ(kHaierAcYrw02ButtonFan, ac.getButton()); } TEST(TestHaierACYRW02Class, OperatingMode) { - IRHaierACYRW02 haier(kGpioUnused); - haier.begin(); + IRHaierACYRW02 ac(kGpioUnused); + ac.begin(); - haier.setButton(kHaierAcYrw02ButtonPower); - haier.setMode(kHaierAcYrw02Auto); - EXPECT_EQ(kHaierAcYrw02Auto, haier.getMode()); - EXPECT_EQ(kHaierAcYrw02ButtonMode, haier.getButton()); + ac.setButton(kHaierAcYrw02ButtonPower); + ac.setMode(kHaierAcYrw02Auto); + EXPECT_EQ(kHaierAcYrw02Auto, ac.getMode()); + EXPECT_EQ(kHaierAcYrw02ButtonMode, ac.getButton()); - haier.setMode(kHaierAcYrw02Cool); - EXPECT_EQ(kHaierAcYrw02Cool, haier.getMode()); + ac.setMode(kHaierAcYrw02Cool); + EXPECT_EQ(kHaierAcYrw02Cool, ac.getMode()); - haier.setMode(kHaierAcYrw02Heat); - EXPECT_EQ(kHaierAcYrw02Heat, haier.getMode()); + ac.setMode(kHaierAcYrw02Heat); + EXPECT_EQ(kHaierAcYrw02Heat, ac.getMode()); - haier.setMode(kHaierAcYrw02Fan); - EXPECT_EQ(kHaierAcYrw02Fan, haier.getMode()); + ac.setMode(kHaierAcYrw02Fan); + EXPECT_EQ(kHaierAcYrw02Fan, ac.getMode()); - haier.setMode(kHaierAcYrw02Dry); - EXPECT_EQ(kHaierAcYrw02Dry, haier.getMode()); + ac.setMode(kHaierAcYrw02Dry); + EXPECT_EQ(kHaierAcYrw02Dry, ac.getMode()); - haier.setMode(kHaierAcYrw02Auto - 1); - EXPECT_EQ(kHaierAcYrw02Auto, haier.getMode()); + ac.setMode(kHaierAcYrw02Auto - 1); + EXPECT_EQ(kHaierAcYrw02Auto, ac.getMode()); - haier.setMode(kHaierAcYrw02Cool); - EXPECT_EQ(kHaierAcYrw02Cool, haier.getMode()); + ac.setMode(kHaierAcYrw02Cool); + EXPECT_EQ(kHaierAcYrw02Cool, ac.getMode()); - haier.setMode(kHaierAcYrw02Fan + 1); - EXPECT_EQ(kHaierAcYrw02Auto, haier.getMode()); + ac.setMode(kHaierAcYrw02Fan + 1); + EXPECT_EQ(kHaierAcYrw02Auto, ac.getMode()); - haier.setMode(255); - EXPECT_EQ(kHaierAcYrw02Auto, haier.getMode()); + ac.setMode(255); + EXPECT_EQ(kHaierAcYrw02Auto, ac.getMode()); } TEST(TestHaierACYRW02Class, Temperature) { - IRHaierACYRW02 haier(kGpioUnused); - haier.begin(); + IRHaierACYRW02 ac(kGpioUnused); + ac.begin(); - haier.setTemp(kHaierAcMinTemp); - EXPECT_EQ(kHaierAcMinTemp, haier.getTemp()); + ac.setTemp(kHaierAcYrw02MinTempC); + EXPECT_EQ(kHaierAcYrw02MinTempC, ac.getTemp()); - haier.setButton(kHaierAcYrw02ButtonPower); - haier.setTemp(kHaierAcMinTemp + 1); - EXPECT_EQ(kHaierAcMinTemp + 1, haier.getTemp()); - EXPECT_EQ(kHaierAcYrw02ButtonTempUp, haier.getButton()); + ac.setButton(kHaierAcYrw02ButtonPower); + ac.setTemp(kHaierAcYrw02MinTempC + 1); + EXPECT_EQ(kHaierAcYrw02MinTempC + 1, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton()); - haier.setTemp(kHaierAcMaxTemp); - EXPECT_EQ(kHaierAcMaxTemp, haier.getTemp()); - EXPECT_EQ(kHaierAcYrw02ButtonTempUp, haier.getButton()); + ac.setTemp(kHaierAcYrw02MaxTempC); + EXPECT_EQ(kHaierAcYrw02MaxTempC, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton()); - haier.setTemp(kHaierAcMinTemp - 1); - EXPECT_EQ(kHaierAcMinTemp, haier.getTemp()); - EXPECT_EQ(kHaierAcYrw02ButtonTempDown, haier.getButton()); + ac.setTemp(kHaierAcYrw02MinTempC - 1); + EXPECT_EQ(kHaierAcYrw02MinTempC, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempDown, ac.getButton()); - haier.setTemp(kHaierAcMaxTemp + 1); - EXPECT_EQ(kHaierAcMaxTemp, haier.getTemp()); - EXPECT_EQ(kHaierAcYrw02ButtonTempUp, haier.getButton()); + ac.setTemp(kHaierAcYrw02MaxTempC + 1); + EXPECT_EQ(kHaierAcYrw02MaxTempC, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton()); - haier.setTemp(23); - EXPECT_EQ(23, haier.getTemp()); - EXPECT_EQ(kHaierAcYrw02ButtonTempDown, haier.getButton()); - haier.setButton(kHaierAcYrw02ButtonPower); - haier.setTemp(23); - EXPECT_EQ(23, haier.getTemp()); - EXPECT_EQ(kHaierAcYrw02ButtonPower, haier.getButton()); + ac.setTemp(23); + EXPECT_EQ(23, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempDown, ac.getButton()); + ac.setButton(kHaierAcYrw02ButtonPower); + ac.setTemp(23); + EXPECT_EQ(23, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonPower, ac.getButton()); - haier.setTemp(0); - EXPECT_EQ(kHaierAcMinTemp, haier.getTemp()); - EXPECT_EQ(kHaierAcYrw02ButtonTempDown, haier.getButton()); + ac.setTemp(kHaierAcYrw02MinTempF, true); + EXPECT_EQ(kHaierAcYrw02MinTempF, ac.getTemp()); - haier.setTemp(255); - EXPECT_EQ(kHaierAcMaxTemp, haier.getTemp()); - EXPECT_EQ(kHaierAcYrw02ButtonTempUp, haier.getButton()); + ac.setButton(kHaierAcYrw02ButtonPower); + ac.setTemp(kHaierAcYrw02MinTempF + 1, true); + EXPECT_EQ(kHaierAcYrw02MinTempF + 1, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton()); + + ac.setTemp(kHaierAcYrw02MaxTempF, true); + EXPECT_EQ(kHaierAcYrw02MaxTempF, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton()); + + ac.setTemp(kHaierAcYrw02MinTempF - 1, true); + EXPECT_EQ(kHaierAcYrw02MinTempF, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempDown, ac.getButton()); + + ac.setTemp(kHaierAcYrw02MaxTempF + 1, true); + EXPECT_EQ(kHaierAcYrw02MaxTempF, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton()); + + ac.setTemp(66, true); + EXPECT_EQ(66, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempDown, ac.getButton()); + ac.setButton(kHaierAcYrw02ButtonPower); + ac.setTemp(66, true); + EXPECT_EQ(66, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonPower, ac.getButton()); + + // Test specific cases for converting to Fahrenheit + ac.setTemp(76, true); + EXPECT_EQ(76, ac.getTemp()); + ac.setTemp(77, true); + EXPECT_EQ(77, ac.getTemp()); + ac.setTemp(78, true); + EXPECT_EQ(78, ac.getTemp()); + + ac.setTemp(24); + EXPECT_EQ(kHaierAcYrw02ButtonCFAB, ac.getButton()); + + ac.setTemp(0); + EXPECT_EQ(kHaierAcYrw02MinTempC, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempDown, ac.getButton()); + + ac.setTemp(255); + EXPECT_EQ(kHaierAcMaxTemp, ac.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton()); } TEST(TestHaierACYRW02Class, HealthMode) { - IRHaierACYRW02 haier(kGpioUnused); - haier.begin(); + IRHaierACYRW02 ac(kGpioUnused); + ac.begin(); - haier.setHealth(true); - EXPECT_TRUE(haier.getHealth()); - EXPECT_EQ(kHaierAcYrw02ButtonHealth, haier.getButton()); + ac.setHealth(true); + EXPECT_TRUE(ac.getHealth()); + EXPECT_EQ(kHaierAcYrw02ButtonHealth, ac.getButton()); - haier.setButton(kHaierAcYrw02ButtonTempUp); - haier.setHealth(false); - EXPECT_FALSE(haier.getHealth()); - EXPECT_EQ(kHaierAcYrw02ButtonHealth, haier.getButton()); + ac.setButton(kHaierAcYrw02ButtonTempUp); + ac.setHealth(false); + EXPECT_FALSE(ac.getHealth()); + EXPECT_EQ(kHaierAcYrw02ButtonHealth, ac.getButton()); - haier.setHealth(true); - EXPECT_TRUE(haier.getHealth()); - EXPECT_EQ(kHaierAcYrw02ButtonHealth, haier.getButton()); + ac.setHealth(true); + EXPECT_TRUE(ac.getHealth()); + EXPECT_EQ(kHaierAcYrw02ButtonHealth, ac.getButton()); } TEST(TestHaierACYRW02Class, Power) { - IRHaierACYRW02 haier(kGpioUnused); - haier.begin(); + IRHaierACYRW02 ac(kGpioUnused); + ac.begin(); - haier.setPower(true); - EXPECT_TRUE(haier.getPower()); - EXPECT_EQ(kHaierAcYrw02ButtonPower, haier.getButton()); + ac.setPower(true); + EXPECT_TRUE(ac.getPower()); + EXPECT_EQ(kHaierAcYrw02ButtonPower, ac.getButton()); - haier.setButton(kHaierAcYrw02ButtonTempUp); - haier.setPower(false); - EXPECT_FALSE(haier.getPower()); - EXPECT_EQ(kHaierAcYrw02ButtonPower, haier.getButton()); + ac.setButton(kHaierAcYrw02ButtonTempUp); + ac.setPower(false); + EXPECT_FALSE(ac.getPower()); + EXPECT_EQ(kHaierAcYrw02ButtonPower, ac.getButton()); - haier.setPower(true); - EXPECT_TRUE(haier.getPower()); - EXPECT_EQ(kHaierAcYrw02ButtonPower, haier.getButton()); + ac.setPower(true); + EXPECT_TRUE(ac.getPower()); + EXPECT_EQ(kHaierAcYrw02ButtonPower, ac.getButton()); - haier.off(); - EXPECT_FALSE(haier.getPower()); - haier.on(); - EXPECT_TRUE(haier.getPower()); + ac.off(); + EXPECT_FALSE(ac.getPower()); + ac.on(); + EXPECT_TRUE(ac.getPower()); } TEST(TestHaierACYRW02Class, SleepMode) { - IRHaierACYRW02 haier(kGpioUnused); - haier.begin(); + IRHaierACYRW02 ac(kGpioUnused); + ac.begin(); - haier.setSleep(true); - EXPECT_TRUE(haier.getSleep()); - EXPECT_EQ(kHaierAcYrw02ButtonSleep, haier.getButton()); + ac.setSleep(true); + EXPECT_TRUE(ac.getSleep()); + EXPECT_EQ(kHaierAcYrw02ButtonSleep, ac.getButton()); - haier.setButton(kHaierAcYrw02ButtonTempUp); - haier.setSleep(false); - EXPECT_FALSE(haier.getSleep()); - EXPECT_EQ(kHaierAcYrw02ButtonSleep, haier.getButton()); + ac.setButton(kHaierAcYrw02ButtonTempUp); + ac.setSleep(false); + EXPECT_FALSE(ac.getSleep()); + EXPECT_EQ(kHaierAcYrw02ButtonSleep, ac.getButton()); - haier.setSleep(true); - EXPECT_TRUE(haier.getSleep()); - EXPECT_EQ(kHaierAcYrw02ButtonSleep, haier.getButton()); + ac.setSleep(true); + EXPECT_TRUE(ac.getSleep()); + EXPECT_EQ(kHaierAcYrw02ButtonSleep, ac.getButton()); } -TEST(TestHaierACYRW02Class, TurboMode) { - IRHaierACYRW02 haier(kGpioUnused); - haier.begin(); +TEST(TestHaierACYRW02Class, TurboAndQuiet) { + IRHaierACYRW02 ac(kGpioUnused); + ac.begin(); - haier.setTurbo(kHaierAcYrw02TurboOff); - EXPECT_EQ(kHaierAcYrw02TurboOff, haier.getTurbo()); - EXPECT_EQ(kHaierAcYrw02ButtonTurbo, haier.getButton()); + ac.setMode(kHaierAcYrw02Cool); // Turbo & Quiet is allowed in this mode. + ac.setTurbo(false); + ac.setQuiet(false); + EXPECT_FALSE(ac.getTurbo()); + EXPECT_FALSE(ac.getQuiet()); + EXPECT_EQ(kHaierAcYrw02ButtonTurbo, ac.getButton()); - haier.setButton(kHaierAcYrw02ButtonTempUp); + ac.setButton(kHaierAcYrw02ButtonTempUp); - haier.setTurbo(kHaierAcYrw02TurboLow); - EXPECT_EQ(kHaierAcYrw02TurboLow, haier.getTurbo()); - EXPECT_EQ(kHaierAcYrw02ButtonTurbo, haier.getButton()); + ac.setTurbo(true); + EXPECT_TRUE(ac.getTurbo()); + EXPECT_FALSE(ac.getQuiet()); + EXPECT_EQ(kHaierAcYrw02ButtonTurbo, ac.getButton()); - haier.setTurbo(kHaierAcYrw02TurboHigh); - EXPECT_EQ(kHaierAcYrw02TurboHigh, haier.getTurbo()); - EXPECT_EQ(kHaierAcYrw02ButtonTurbo, haier.getButton()); + ac.setQuiet(true); + EXPECT_FALSE(ac.getTurbo()); + EXPECT_TRUE(ac.getQuiet()); + EXPECT_EQ(kHaierAcYrw02ButtonTurbo, ac.getButton()); - haier.setTurbo(kHaierAcYrw02TurboOff); - EXPECT_EQ(kHaierAcYrw02TurboOff, haier.getTurbo()); - EXPECT_EQ(kHaierAcYrw02ButtonTurbo, haier.getButton()); + ac.setTurbo(false); + ac.setQuiet(false); + EXPECT_FALSE(ac.getTurbo()); + EXPECT_FALSE(ac.getQuiet()); + EXPECT_EQ(kHaierAcYrw02ButtonTurbo, ac.getButton()); + + ac.setMode(kHaierAcYrw02Auto); // Turbo & Quiet is not allowed in this mode. + EXPECT_FALSE(ac.getTurbo()); + EXPECT_FALSE(ac.getQuiet()); + ac.setTurbo(true); + EXPECT_FALSE(ac.getTurbo()); + EXPECT_NE(kHaierAcYrw02ButtonTurbo, ac.getButton()); + ac.setQuiet(true); + EXPECT_FALSE(ac.getQuiet()); + EXPECT_NE(kHaierAcYrw02ButtonTurbo, ac.getButton()); } TEST(TestHaierACYRW02Class, Fan) { - IRHaierACYRW02 haier(kGpioUnused); - haier.begin(); + IRHaierACYRW02 ac(kGpioUnused); + ac.begin(); - haier.setFan(kHaierAcYrw02FanAuto); - EXPECT_EQ(kHaierAcYrw02FanAuto, haier.getFan()); - EXPECT_EQ(kHaierAcYrw02ButtonFan, haier.getButton()); + ac.setFan(kHaierAcYrw02FanAuto); + EXPECT_EQ(kHaierAcYrw02FanAuto, ac.getFan()); + EXPECT_EQ(kHaierAcYrw02ButtonFan, ac.getButton()); - haier.setButton(kHaierAcYrw02ButtonTempUp); + ac.setButton(kHaierAcYrw02ButtonTempUp); - haier.setFan(kHaierAcYrw02FanLow); - EXPECT_EQ(kHaierAcYrw02FanLow, haier.getFan()); - EXPECT_EQ(kHaierAcYrw02ButtonFan, haier.getButton()); + ac.setFan(kHaierAcYrw02FanLow); + EXPECT_EQ(kHaierAcYrw02FanLow, ac.getFan()); + EXPECT_EQ(kHaierAcYrw02ButtonFan, ac.getButton()); - haier.setFan(kHaierAcYrw02FanHigh); - EXPECT_EQ(kHaierAcYrw02FanHigh, haier.getFan()); - EXPECT_EQ(kHaierAcYrw02ButtonFan, haier.getButton()); + ac.setFan(kHaierAcYrw02FanHigh); + EXPECT_EQ(kHaierAcYrw02FanHigh, ac.getFan()); + EXPECT_EQ(kHaierAcYrw02ButtonFan, ac.getButton()); - haier.setFan(kHaierAcYrw02FanMed); - EXPECT_EQ(kHaierAcYrw02FanMed, haier.getFan()); - EXPECT_EQ(kHaierAcYrw02ButtonFan, haier.getButton()); + ac.setFan(kHaierAcYrw02FanMed); + EXPECT_EQ(kHaierAcYrw02FanMed, ac.getFan()); + EXPECT_EQ(kHaierAcYrw02ButtonFan, ac.getButton()); // Test unexpected values. - haier.setButton(kHaierAcYrw02ButtonTempUp); - haier.setFan(0x00); - EXPECT_EQ(kHaierAcYrw02FanMed, haier.getFan()); - EXPECT_EQ(kHaierAcYrw02ButtonTempUp, haier.getButton()); + ac.setButton(kHaierAcYrw02ButtonTempUp); + ac.setFan(0x00); + EXPECT_EQ(kHaierAcYrw02FanMed, ac.getFan()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton()); } -TEST(TestHaierACYRW02Class, Swing) { - IRHaierACYRW02 haier(kGpioUnused); - haier.begin(); +TEST(TestHaierACYRW02Class, SwingV) { + IRHaierACYRW02 ac(kGpioUnused); + ac.begin(); - haier.setSwing(kHaierAcYrw02SwingOff); - EXPECT_EQ(kHaierAcYrw02SwingOff, haier.getSwing()); - EXPECT_EQ(kHaierAcYrw02ButtonSwing, haier.getButton()); + ac.setSwingV(kHaierAcYrw02SwingVOff); + EXPECT_EQ(kHaierAcYrw02SwingVOff, ac.getSwingV()); + EXPECT_EQ(kHaierAcYrw02ButtonSwingV, ac.getButton()); - haier.setButton(kHaierAcYrw02ButtonTempUp); + ac.setButton(kHaierAcYrw02ButtonTempUp); - haier.setSwing(kHaierAcYrw02SwingAuto); - EXPECT_EQ(kHaierAcYrw02SwingAuto, haier.getSwing()); - EXPECT_EQ(kHaierAcYrw02ButtonSwing, haier.getButton()); + ac.setSwingV(kHaierAcYrw02SwingVAuto); + EXPECT_EQ(kHaierAcYrw02SwingVAuto, ac.getSwingV()); + EXPECT_EQ(kHaierAcYrw02ButtonSwingV, ac.getButton()); - haier.setSwing(kHaierAcYrw02SwingTop); - EXPECT_EQ(kHaierAcYrw02SwingTop, haier.getSwing()); - EXPECT_EQ(kHaierAcYrw02ButtonSwing, haier.getButton()); + ac.setSwingV(kHaierAcYrw02SwingVTop); + EXPECT_EQ(kHaierAcYrw02SwingVTop, ac.getSwingV()); + EXPECT_EQ(kHaierAcYrw02ButtonSwingV, ac.getButton()); - haier.setSwing(kHaierAcYrw02SwingDown); - EXPECT_EQ(kHaierAcYrw02SwingDown, haier.getSwing()); - EXPECT_EQ(kHaierAcYrw02ButtonSwing, haier.getButton()); + ac.setSwingV(kHaierAcYrw02SwingVDown); + EXPECT_EQ(kHaierAcYrw02SwingVDown, ac.getSwingV()); + EXPECT_EQ(kHaierAcYrw02ButtonSwingV, ac.getButton()); // Test unexpected values. - haier.setButton(kHaierAcYrw02ButtonTempUp); - haier.setSwing(0xFF); - EXPECT_EQ(kHaierAcYrw02SwingDown, haier.getSwing()); - EXPECT_EQ(kHaierAcYrw02ButtonTempUp, haier.getButton()); + ac.setButton(kHaierAcYrw02ButtonTempUp); + ac.setSwingV(0xFF); + EXPECT_EQ(kHaierAcYrw02SwingVDown, ac.getSwingV()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton()); // Test the mode-dependant positions. - haier.setMode(kHaierAcYrw02Auto); - haier.setSwing(kHaierAcYrw02SwingMiddle); - EXPECT_EQ(kHaierAcYrw02SwingMiddle, haier.getSwing()); - EXPECT_EQ(kHaierAcYrw02ButtonSwing, haier.getButton()); - haier.setMode(kHaierAcYrw02Heat); - haier.setSwing(kHaierAcYrw02SwingMiddle); - EXPECT_EQ(kHaierAcYrw02SwingBottom, haier.getSwing()); - haier.setSwing(kHaierAcYrw02SwingAuto); - EXPECT_EQ(kHaierAcYrw02SwingAuto, haier.getSwing()); - haier.setSwing(kHaierAcYrw02SwingBottom); - EXPECT_EQ(kHaierAcYrw02SwingBottom, haier.getSwing()); - haier.setMode(kHaierAcYrw02Cool); - haier.setSwing(kHaierAcYrw02SwingBottom); - EXPECT_EQ(kHaierAcYrw02SwingMiddle, haier.getSwing()); + ac.setMode(kHaierAcYrw02Auto); + ac.setSwingV(kHaierAcYrw02SwingVMiddle); + EXPECT_EQ(kHaierAcYrw02SwingVMiddle, ac.getSwingV()); + EXPECT_EQ(kHaierAcYrw02ButtonSwingV, ac.getButton()); + ac.setMode(kHaierAcYrw02Heat); + ac.setSwingV(kHaierAcYrw02SwingVMiddle); + EXPECT_EQ(kHaierAcYrw02SwingVBottom, ac.getSwingV()); + ac.setSwingV(kHaierAcYrw02SwingVAuto); + EXPECT_EQ(kHaierAcYrw02SwingVAuto, ac.getSwingV()); + ac.setSwingV(kHaierAcYrw02SwingVBottom); + EXPECT_EQ(kHaierAcYrw02SwingVBottom, ac.getSwingV()); + ac.setMode(kHaierAcYrw02Cool); + ac.setSwingV(kHaierAcYrw02SwingVBottom); + EXPECT_EQ(kHaierAcYrw02SwingVMiddle, ac.getSwingV()); +} + +TEST(TestHaierACYRW02Class, SwingH) { + IRHaierACYRW02 ac(kGpioUnused); + ac.begin(); + + ac.setSwingH(kHaierAcYrw02SwingVOff); + EXPECT_EQ(kHaierAcYrw02SwingHMiddle, ac.getSwingH()); + EXPECT_EQ(kHaierAcYrw02ButtonSwingH, ac.getButton()); + + ac.setButton(kHaierAcYrw02ButtonTempUp); + + ac.setSwingH(kHaierAcYrw02SwingHLeftMax); + EXPECT_EQ(kHaierAcYrw02SwingHLeftMax, ac.getSwingH()); + EXPECT_EQ(kHaierAcYrw02ButtonSwingH, ac.getButton()); + + ac.setSwingH(kHaierAcYrw02SwingHLeft); + EXPECT_EQ(kHaierAcYrw02SwingHLeft, ac.getSwingH()); + EXPECT_EQ(kHaierAcYrw02ButtonSwingH, ac.getButton()); + + ac.setSwingH(kHaierAcYrw02SwingHRight); + EXPECT_EQ(kHaierAcYrw02SwingHRight, ac.getSwingH()); + EXPECT_EQ(kHaierAcYrw02ButtonSwingH, ac.getButton()); + + ac.setSwingH(kHaierAcYrw02SwingHRightMax); + EXPECT_EQ(kHaierAcYrw02SwingHRightMax, ac.getSwingH()); + EXPECT_EQ(kHaierAcYrw02ButtonSwingH, ac.getButton()); + + ac.setSwingH(kHaierAcYrw02SwingHAuto); + EXPECT_EQ(kHaierAcYrw02SwingHAuto, ac.getSwingH()); + EXPECT_EQ(kHaierAcYrw02ButtonSwingH, ac.getButton()); + + // Test unexpected values. + ac.setButton(kHaierAcYrw02ButtonTempUp); + ac.setSwingH(0xFF); + EXPECT_EQ(kHaierAcYrw02SwingHAuto, ac.getSwingH()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, ac.getButton()); +} + +TEST(TestHaierACYRW02Class, Lock) { + IRHaierACYRW02 ac(kGpioUnused); + ac.begin(); + + ac.setLock(true); + EXPECT_TRUE(ac.getLock()); + EXPECT_EQ(kHaierAcYrw02ButtonLock, ac.getButton()); + + ac.setButton(kHaierAcYrw02ButtonTempUp); + ac.setLock(false); + EXPECT_FALSE(ac.getLock()); + EXPECT_EQ(kHaierAcYrw02ButtonLock, ac.getButton()); + + ac.setLock(true); + EXPECT_TRUE(ac.getLock()); + EXPECT_EQ(kHaierAcYrw02ButtonLock, ac.getButton()); } TEST(TestHaierACYRW02Class, MessageConstuction) { - IRHaierACYRW02 haier(kGpioUnused); + IRHaierACYRW02 ac(kGpioUnused); EXPECT_EQ( - "Power: On, Button: 5 (Power), Mode: 0 (Auto), Temp: 25C," - " Fan: 5 (Auto), Turbo: 0 (Off), Swing: 0 (Off), Sleep: Off," - " Health: On, Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off", - haier.toString()); - haier.setMode(kHaierAcYrw02Cool); - haier.setTemp(21); - haier.setFan(kHaierAcYrw02FanHigh); + "Model: 1 (V9014557-A), Power: On, Button: 5 (Power), " + "Mode: 0 (Auto), Temp: 25C, Fan: 5 (Auto), Turbo: Off, Quiet: Off, " + "Swing(V): 0 (Off), Swing(H): 0 (Middle), Sleep: Off, Health: On, " + "Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off, Lock: Off", + ac.toString()); + ac.setMode(kHaierAcYrw02Cool); + ac.setTemp(21); + ac.setFan(kHaierAcYrw02FanHigh); EXPECT_EQ( - "Power: On, Button: 4 (Fan), Mode: 1 (Cool), Temp: 21C," - " Fan: 1 (High), Turbo: 0 (Off), Swing: 0 (Off), Sleep: Off," - " Health: On, Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off", - haier.toString()); + "Model: 1 (V9014557-A), Power: On, Button: 4 (Fan), " + "Mode: 1 (Cool), Temp: 21C, Fan: 1 (High), Turbo: Off, Quiet: Off, " + "Swing(V): 0 (Off), Swing(H): 0 (Middle), Sleep: Off, Health: On, " + "Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off, Lock: Off", + ac.toString()); - haier.setSwing(kHaierAcYrw02SwingMiddle); - haier.setHealth(false); - haier.setSleep(true); - haier.setTurbo(kHaierAcYrw02TurboHigh); + ac.setTemp(75, true); + ac.setSwingV(kHaierAcYrw02SwingVMiddle); + ac.setHealth(false); + ac.setSleep(true); + ac.setTurbo(true); EXPECT_EQ( - "Power: On, Button: 8 (Turbo), Mode: 1 (Cool), Temp: 21C, " - "Fan: 1 (High), Turbo: 1 (High), Swing: 2 (Middle), " - "Sleep: On, Health: Off, " - "Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off", - haier.toString()); + "Model: 1 (V9014557-A), Power: On, Button: 8 (Turbo), " + "Mode: 1 (Cool), Temp: 75F, Fan: 1 (High), Turbo: On, Quiet: Off, " + "Swing(V): 2 (Middle), Swing(H): 0 (Middle), Sleep: On, Health: Off, " + "Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off, Lock: Off", + ac.toString()); } // Decode "real" state messages. @@ -704,55 +818,60 @@ TEST(TestHaierACYRW02Class, RealStates) { 0xA6, 0xE1, 0x00, 0x00, 0x40, 0x20, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0x6E}; - IRHaierACYRW02 haier(kGpioUnused); - haier.setRaw(expectedState1); + IRHaierACYRW02 ac(kGpioUnused); + ac.setRaw(expectedState1); EXPECT_EQ( - "Power: On, Button: 7 (Health), Mode: 4 (Heat), Temp: 30C, " - "Fan: 1 (High), Turbo: 0 (Off), Swing: 1 (Highest), Sleep: Off, " - "Health: Off, Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off", - haier.toString()); + "Model: 1 (V9014557-A), Power: On, Button: 7 (Health), " + "Mode: 4 (Heat), Temp: 30C, Fan: 1 (High), Turbo: Off, Quiet: Off, " + "Swing(V): 1 (Highest), Swing(H): 0 (Middle), Sleep: Off, Health: Off, " + "Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off, Lock: Off", + ac.toString()); uint8_t expectedState2[kHaierACYRW02StateLength] = { 0xA6, 0xE0, 0x00, 0x00, 0x00, 0x20, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x05, 0x75}; - haier.setRaw(expectedState2); + ac.setRaw(expectedState2); EXPECT_EQ( - "Power: Off, Button: 5 (Power), Mode: 4 (Heat), Temp: 30C, " - "Fan: 1 (High), Turbo: 0 (Off), Swing: 0 (Off), Sleep: Off, " - "Health: Off, Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off", - haier.toString()); + "Model: 1 (V9014557-A), Power: Off, Button: 5 (Power), " + "Mode: 4 (Heat), Temp: 30C, Fan: 1 (High), Turbo: Off, Quiet: Off, " + "Swing(V): 0 (Off), Swing(H): 0 (Middle), Sleep: Off, Health: Off, " + "Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off, Lock: Off", + ac.toString()); uint8_t expectedState3[kHaierACYRW02StateLength] = { 0xA6, 0x02, 0x00, 0x02, 0x40, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2B}; - haier.setRaw(expectedState3); + ac.setRaw(expectedState3); EXPECT_EQ( - "Power: On, Button: 1 (Temp Down), Mode: 1 (Cool), Temp: 16C, " - "Fan: 1 (High), Turbo: 0 (Off), Swing: 2 (Middle), Sleep: Off, " - "Health: On, Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off", - haier.toString()); + "Model: 1 (V9014557-A), Power: On, Button: 1 (Temp Down), " + "Mode: 1 (Cool), Temp: 16C, Fan: 1 (High), Turbo: Off, Quiet: Off, " + "Swing(V): 2 (Middle), Swing(H): 0 (Middle), Sleep: Off, Health: On, " + "Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off, Lock: Off", + ac.toString()); - // cool 25, health, fan auto, swing auto, sleep on + // cool 25, health, fan auto, vertical swing auto, sleep on uint8_t expectedState4[kHaierACYRW02StateLength] = { 0xA6, 0x9C, 0x00, 0x02, 0x40, 0xA8, 0x00, 0x20, 0x80, 0x00, 0x00, 0x00, 0x0B, 0xD7}; - haier.setRaw(expectedState4); + ac.setRaw(expectedState4); EXPECT_EQ( - "Power: On, Button: 11 (Sleep), Mode: 1 (Cool), Temp: 25C, " - "Fan: 5 (Auto), Turbo: 0 (Off), Swing: 12 (Auto), Sleep: On, " - "Health: On, Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off", - haier.toString()); + "Model: 1 (V9014557-A), Power: On, Button: 11 (Sleep), " + "Mode: 1 (Cool), Temp: 25C, Fan: 5 (Auto), Turbo: Off, Quiet: Off, " + "Swing(V): 12 (Auto), Swing(H): 0 (Middle), Sleep: On, Health: On, " + "Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off, Lock: Off", + ac.toString()); - // cool 25, health, fan 3, swing auto, sleep on + // cool 25, health, fan 3, vertical swing auto, sleep on uint8_t expectedState5[kHaierACYRW02StateLength] = { 0xA6, 0x9C, 0x00, 0x02, 0x40, 0x27, 0x36, 0x20, 0x80, 0x00, 0x00, 0x00, 0x04, 0x85}; - haier.setRaw(expectedState5); + ac.setRaw(expectedState5); EXPECT_EQ( - "Power: On, Button: 4 (Fan), Mode: 1 (Cool), Temp: 25C, " - "Fan: 1 (High), Turbo: 0 (Off), Swing: 12 (Auto), Sleep: On, " - "Health: On, Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off", - haier.toString()); + "Model: 1 (V9014557-A), Power: On, Button: 4 (Fan), " + "Mode: 1 (Cool), Temp: 25C, Fan: 1 (High), Turbo: Off, Quiet: Off, " + "Swing(V): 12 (Auto), Swing(H): 0 (Middle), Sleep: On, Health: On, " + "Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off, Lock: Off", + ac.toString()); } // Tests for decodeHaierAC(). @@ -823,7 +942,7 @@ TEST(TestDecodeHaierAC, RealExample1) { EXPECT_EQ( "Command: 1 (On), Mode: 1 (Cool), Temp: 16C, Fan: 1 (Low), " - "Swing: 0 (Off), Sleep: Off, Health: Off, " + "Swing(V): 0 (Off), Sleep: Off, Health: Off, " "Clock: 00:01, On Timer: Off, Off Timer: Off", IRAcUtils::resultAcToString(&irsend.capture)); stdAc::state_t r, p; @@ -864,13 +983,13 @@ TEST(TestDecodeHaierAC, RealExample2) { EXPECT_FALSE(irsend.capture.repeat); EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); - IRHaierAC haier(kGpioUnused); - haier.setRaw(irsend.capture.state); + IRHaierAC ac(kGpioUnused); + ac.setRaw(irsend.capture.state); EXPECT_EQ( "Command: 6 (Temp Up), Mode: 1 (Cool), Temp: 22C, Fan: 1 (Low), " - "Swing: 0 (Off), Sleep: Off, Health: Off, " + "Swing(V): 0 (Off), Sleep: Off, Health: Off, " "Clock: 00:01, On Timer: Off, Off Timer: Off", - haier.toString()); + ac.toString()); } // Decode a "real" example message. @@ -907,13 +1026,13 @@ TEST(TestDecodeHaierAC, RealExample3) { EXPECT_FALSE(irsend.capture.repeat); EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); - IRHaierAC haier(kGpioUnused); - haier.setRaw(irsend.capture.state); + IRHaierAC ac(kGpioUnused); + ac.setRaw(irsend.capture.state); EXPECT_EQ( "Command: 12 (Health), Mode: 1 (Cool), Temp: 30C, Fan: 1 (Low), " - "Swing: 0 (Off), Sleep: Off, Health: On, " + "Swing(V): 0 (Off), Sleep: Off, Health: On, " "Clock: 00:09, On Timer: Off, Off Timer: Off", - haier.toString()); + ac.toString()); } // Decode normal "synthetic" messages. @@ -977,13 +1096,14 @@ TEST(TestDecodeHaierAC_YRW02, RealExample) { EXPECT_FALSE(irsend.capture.repeat); EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); - IRHaierACYRW02 haier(kGpioUnused); - haier.setRaw(irsend.capture.state); + IRHaierACYRW02 ac(kGpioUnused); + ac.setRaw(irsend.capture.state); EXPECT_EQ( - "Power: On, Button: 5 (Power), Mode: 1 (Cool), Temp: 17C, " - "Fan: 1 (High), Turbo: 0 (Off), Swing: 2 (Middle), Sleep: Off, " - "Health: On, Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off", - haier.toString()); + "Model: 1 (V9014557-A), Power: On, Button: 5 (Power), " + "Mode: 1 (Cool), Temp: 17C, Fan: 1 (High), Turbo: Off, Quiet: Off, " + "Swing(V): 2 (Middle), Swing(H): 0 (Middle), Sleep: Off, Health: On, " + "Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off, Lock: Off", + ac.toString()); } // Default state of the remote needed to include hidden data. @@ -998,7 +1118,7 @@ TEST(TestHaierAcIssues, Issue668) { ac._irsend.reset(); char expected_on[] = "Command: 1 (On), Mode: 1 (Cool), Temp: 25C, Fan: 1 (Low), " - "Swing: 0 (Off), Sleep: Off, Health: Off, Clock: 00:00, " + "Swing(V): 0 (Off), Sleep: Off, Health: Off, Clock: 00:00, " "On Timer: Off, Off Timer: Off"; // State taken from real capture: // https://github.com/crankyoldgit/IRremoteESP8266/issues/668#issuecomment-483531895 @@ -1036,7 +1156,7 @@ TEST(TestHaierAcIssues, Issue668) { ac._irsend.reset(); char expected_temp_plus_one[] = "Command: 6 (Temp Up), Mode: 1 (Cool), Temp: 26C, Fan: 1 (Low), " - "Swing: 0 (Off), Sleep: Off, Health: Off, Clock: 00:00, " + "Swing(V): 0 (Off), Sleep: Off, Health: Off, Clock: 00:00, " "On Timer: Off, Off Timer: Off"; // State taken from real capture: // https://github.com/crankyoldgit/IRremoteESP8266/issues/668#issuecomment-483531895 @@ -1060,7 +1180,7 @@ TEST(TestHaierAcIssues, Issue668) { ac._irsend.reset(); char expected_temp_minus_one[] = "Command: 7 (Temp Down), Mode: 1 (Cool), Temp: 25C, Fan: 1 (Low), " - "Swing: 0 (Off), Sleep: Off, Health: Off, Clock: 00:00, " + "Swing(V): 0 (Off), Sleep: Off, Health: Off, Clock: 00:00, " "On Timer: Off, Off Timer: Off"; ASSERT_EQ(26, ac.getTemp()); ac.setTemp(ac.getTemp() - 1); @@ -1081,7 +1201,7 @@ TEST(TestHaierACClass, toCommon) { ac.setMode(kHaierAcCool); ac.setTemp(20); ac.setFan(kHaierAcFanHigh); - ac.setSwing(kHaierAcSwingChg); + ac.setSwingV(kHaierAcSwingVChg); ac.setHealth(true); ac.setSleep(true); // Now test it. @@ -1102,7 +1222,7 @@ TEST(TestHaierACClass, toCommon) { ASSERT_FALSE(ac.toCommon().quiet); ASSERT_FALSE(ac.toCommon().econo); ASSERT_FALSE(ac.toCommon().clean); - ASSERT_FALSE(ac.toCommon().beep); + ASSERT_TRUE(ac.toCommon().beep); ASSERT_EQ(-1, ac.toCommon().clock); } @@ -1112,12 +1232,14 @@ TEST(TestHaierACYRW02Class, toCommon) { ac.setMode(kHaierAcYrw02Cool); ac.setTemp(20); ac.setFan(kHaierAcYrw02FanHigh); - ac.setSwing(kHaierAcYrw02SwingTop); + ac.setSwingV(kHaierAcYrw02SwingVTop); + ac.setSwingH(kHaierAcYrw02SwingHRightMax); ac.setHealth(true); ac.setSleep(true); + ac.setTurbo(true); // Now test it. ASSERT_EQ(decode_type_t::HAIER_AC_YRW02, ac.toCommon().protocol); - ASSERT_EQ(-1, ac.toCommon().model); + ASSERT_EQ(1, ac.toCommon().model); ASSERT_TRUE(ac.toCommon().power); ASSERT_TRUE(ac.toCommon().celsius); ASSERT_EQ(20, ac.toCommon().degrees); @@ -1125,15 +1247,15 @@ TEST(TestHaierACYRW02Class, toCommon) { ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode); ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed); ASSERT_EQ(stdAc::swingv_t::kHighest, ac.toCommon().swingv); + ASSERT_EQ(stdAc::swingh_t::kRightMax, ac.toCommon().swingh); ASSERT_EQ(0, ac.toCommon().sleep); - // Unsupported. - ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh); - ASSERT_FALSE(ac.toCommon().turbo); - ASSERT_FALSE(ac.toCommon().light); + ASSERT_TRUE(ac.toCommon().turbo); ASSERT_FALSE(ac.toCommon().quiet); + // Unsupported. + ASSERT_FALSE(ac.toCommon().light); ASSERT_FALSE(ac.toCommon().econo); ASSERT_FALSE(ac.toCommon().clean); - ASSERT_FALSE(ac.toCommon().beep); + ASSERT_TRUE(ac.toCommon().beep); ASSERT_EQ(-1, ac.toCommon().clock); } @@ -1204,9 +1326,10 @@ TEST(TestDecodeHaierAC176, SyntheticDecode) { EXPECT_FALSE(irsend.capture.repeat); EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); EXPECT_EQ( - "Power: On, Button: 5 (Power), Mode: 1 (Cool), Temp: 24C, Fan: 5 (Auto), " - "Turbo: 0 (Off), Swing: 6 (UNKNOWN), Sleep: Off, Health: Off, " - "Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off", + "Model: 1 (V9014557-A), Power: On, Button: 5 (Power), " + "Mode: 1 (Cool), Temp: 24C, Fan: 5 (Auto), Turbo: Off, Quiet: Off, " + "Swing(V): 6 (UNKNOWN), Swing(H): 0 (Middle), Sleep: Off, Health: Off, " + "Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off, Lock: Off", IRAcUtils::resultAcToString(&irsend.capture)); stdAc::state_t result, prev; ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &result, &prev)); @@ -1245,9 +1368,10 @@ TEST(TestHaierAC176Class, BuildKnownState) { ac.setFan(kHaierAcYrw02FanHigh); EXPECT_TRUE(ac.validChecksum(ac.getRaw())); EXPECT_EQ( - "Power: On, Button: 4 (Fan), Mode: 4 (Heat), Temp: 24C, Fan: 1 (High), " - "Turbo: 0 (Off), Swing: 0 (Off), Sleep: Off, Health: On, " - "Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off", + "Model: 1 (V9014557-A), Power: On, Button: 4 (Fan), " + "Mode: 4 (Heat), Temp: 24C, Fan: 1 (High), Turbo: Off, Quiet: Off, " + "Swing(V): 0 (Off), Swing(H): 0 (Middle), Sleep: Off, Health: On, " + "Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off, Lock: Off", ac.toString()); /* Disabled pending: https://github.com/crankyoldgit/IRremoteESP8266/issues/1480#issuecomment-885636790 @@ -1323,56 +1447,91 @@ TEST(TestHaierAC176Class, Timers) { // Real data. // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1480#issuecomment-894804106 - const uint8_t timer30m[22] = { + const uint8_t timer30m[kHaierAC176StateLength] = { 0xA6, 0x82, 0x00, 0x40, 0x00, 0xA0, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x10, 0x36, 0xB7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB7}; - const uint8_t timeroff[22] = { + const uint8_t timeroff[kHaierAC176StateLength] = { 0xA6, 0x82, 0x00, 0x00, 0x40, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x18, 0xB7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB7}; // https://docs.google.com/spreadsheets/d/1wdOVS08wgK2pEP7hTZLYMmrQ9FZVmLpZF2HjNQaVxlU/edit#gid=0&range=A65 - const uint8_t timeroffthenon[22] = { + const uint8_t timeroffthenon[kHaierAC176StateLength] = { 0xA6, 0x82, 0x00, 0xA0, 0x40, 0xA0, 0x1E, 0x08, 0x00, 0x00, 0x00, 0x00, 0x10, 0xDE, 0xB7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB7}; ac.setRaw(timer30m); EXPECT_EQ(kHaierAcYrw02OnTimer, ac.getTimerMode()); EXPECT_EQ( - "Power: Off, Button: 0 (Temp Up), Mode: 0 (Auto), Temp: 24C, " - "Fan: 5 (Auto), Turbo: 0 (Off), Swing: 2 (Middle), Sleep: Off, " - "Health: Off, Timer Mode: 2 (On), On Timer: 00:30, Off Timer: Off", + "Model: 1 (V9014557-A), Power: Off, Button: 16 (Timer), " + "Mode: 0 (Auto), Temp: 24C, Fan: 5 (Auto), Turbo: Off, Quiet: Off, " + "Swing(V): 2 (Middle), Swing(H): 0 (Middle), Sleep: Off, Health: Off, " + "Timer Mode: 2 (On), On Timer: 00:30, Off Timer: Off, Lock: Off", ac.toString()); ac.setRaw(timeroff); EXPECT_EQ(kHaierAcYrw02NoTimers, ac.getTimerMode()); EXPECT_EQ( - "Power: On, Button: 0 (Temp Up), Mode: 0 (Auto), Temp: 24C, " - "Fan: 5 (Auto), Turbo: 0 (Off), Swing: 2 (Middle), Sleep: Off, " - "Health: Off, Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off", + "Model: 1 (V9014557-A), Power: On, Button: 16 (Timer), " + "Mode: 0 (Auto), Temp: 24C, Fan: 5 (Auto), Turbo: Off, Quiet: Off, " + "Swing(V): 2 (Middle), Swing(H): 0 (Middle), Sleep: Off, Health: Off, " + "Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off, Lock: Off", ac.toString()); ac.setRaw(timeroffthenon); EXPECT_EQ( - "Power: On, Button: 0 (Temp Up), Mode: 0 (Auto), Temp: 24C, " - "Fan: 5 (Auto), Turbo: 0 (Off), Swing: 2 (Middle), Sleep: Off, " - "Health: Off, Timer Mode: 5 (Off-On), On Timer: 08:00, Off Timer: 00:30", + "Model: 1 (V9014557-A), Power: On, Button: 16 (Timer), " + "Mode: 0 (Auto), Temp: 24C, Fan: 5 (Auto), Turbo: Off, Quiet: Off, " + "Swing(V): 2 (Middle), Swing(H): 0 (Middle), Sleep: Off, Health: Off, " + "Timer Mode: 5 (Off-On), On Timer: 08:00, Off Timer: 00:30, Lock: Off", ac.toString()); ac.setTimerMode(kHaierAcYrw02OnThenOffTimer); EXPECT_EQ( - "Power: On, Button: 0 (Temp Up), Mode: 0 (Auto), Temp: 24C, " - "Fan: 5 (Auto), Turbo: 0 (Off), Swing: 2 (Middle), Sleep: Off, " - "Health: Off, Timer Mode: 4 (On-Off), On Timer: 08:00, Off Timer: 00:30", + "Model: 1 (V9014557-A), Power: On, Button: 16 (Timer), " + "Mode: 0 (Auto), Temp: 24C, Fan: 5 (Auto), Turbo: Off, Quiet: Off, " + "Swing(V): 2 (Middle), Swing(H): 0 (Middle), Sleep: Off, Health: Off, " + "Timer Mode: 4 (On-Off), On Timer: 08:00, Off Timer: 00:30, Lock: Off", ac.toString()); ac.setTimerMode(kHaierAcYrw02OffTimer); EXPECT_EQ(0, ac.getOnTimer()); EXPECT_EQ(30, ac.getOffTimer()); EXPECT_EQ( - "Power: On, Button: 0 (Temp Up), Mode: 0 (Auto), Temp: 24C, " - "Fan: 5 (Auto), Turbo: 0 (Off), Swing: 2 (Middle), Sleep: Off, " - "Health: Off, Timer Mode: 1 (Off), On Timer: Off, Off Timer: 00:30", + "Model: 1 (V9014557-A), Power: On, Button: 16 (Timer), " + "Mode: 0 (Auto), Temp: 24C, Fan: 5 (Auto), Turbo: Off, Quiet: Off, " + "Swing(V): 2 (Middle), Swing(H): 0 (Middle), Sleep: Off, Health: Off, " + "Timer Mode: 1 (Off), On Timer: Off, Off Timer: 00:30, Lock: Off", ac.toString()); ac.setTimerMode(kHaierAcYrw02NoTimers); EXPECT_EQ(0, ac.getOnTimer()); EXPECT_EQ(0, ac.getOffTimer()); EXPECT_EQ( - "Power: On, Button: 0 (Temp Up), Mode: 0 (Auto), Temp: 24C, " - "Fan: 5 (Auto), Turbo: 0 (Off), Swing: 2 (Middle), Sleep: Off, " - "Health: Off, Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off", + "Model: 1 (V9014557-A), Power: On, Button: 16 (Timer), " + "Mode: 0 (Auto), Temp: 24C, Fan: 5 (Auto), Turbo: Off, Quiet: Off, " + "Swing(V): 2 (Middle), Swing(H): 0 (Middle), Sleep: Off, Health: Off, " + "Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off, Lock: Off", + ac.toString()); +} + +TEST(TestHaierAC176Class, Models) { + IRHaierAC176 ac(kGpioUnused); + ac.begin(); + EXPECT_EQ(haier_ac176_remote_model_t::V9014557_A, ac.getModel()); + + ac.setButton(kHaierAcYrw02ButtonTempUp); + ac.setModel(haier_ac176_remote_model_t::V9014557_B); + EXPECT_EQ(haier_ac176_remote_model_t::V9014557_B, ac.getModel()); + EXPECT_EQ(kHaierAcYrw02ButtonCFAB, ac.getButton()); + + ac.setButton(kHaierAcYrw02ButtonTempDown); + ac.setModel(haier_ac176_remote_model_t::V9014557_A); + EXPECT_EQ(haier_ac176_remote_model_t::V9014557_A, ac.getModel()); + EXPECT_EQ(kHaierAcYrw02ButtonCFAB, ac.getButton()); + + // Real data. + const uint8_t setmodelb[kHaierAC176StateLength] = { + 0x59, 0x82, 0x00, 0x00, 0x40, 0x60, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0x00, 0x1A, 0x55, 0xB7, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x77}; + ac.setRaw(setmodelb); + EXPECT_EQ(haier_ac176_remote_model_t::V9014557_B, ac.getModel()); + EXPECT_EQ( + "Model: 2 (V9014557-B), Power: On, Button: 26 (Celsius/Fahrenheit), " + "Mode: 6 (Fan), Temp: 24C, Fan: 3 (Low), Turbo: Off, Quiet: Off, " + "Swing(V): 2 (Middle), Swing(H): 0 (Middle), Sleep: Off, Health: Off, " + "Timer Mode: 0 (N/A), On Timer: Off, Off Timer: Off, Lock: Off", ac.toString()); } diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Mirage_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Mirage_test.cpp index 2530afc5c..ad08918e2 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Mirage_test.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Mirage_test.cpp @@ -1,5 +1,6 @@ -// Copyright 2020 David Conran +// Copyright 2020-2021 David Conran +#include "ir_Mirage.h" #include "IRac.h" #include "IRrecv.h" #include "IRrecv_test.h" @@ -11,7 +12,7 @@ TEST(TestUtils, Housekeeping) { ASSERT_EQ("MIRAGE", typeToString(decode_type_t::MIRAGE)); ASSERT_EQ(decode_type_t::MIRAGE, strToDecodeType("MIRAGE")); ASSERT_TRUE(hasACState(decode_type_t::MIRAGE)); - ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::MIRAGE)); + ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::MIRAGE)); ASSERT_EQ(kMirageBits, IRsend::defaultBits(decode_type_t::MIRAGE)); ASSERT_EQ(kMirageMinRepeat, IRsend::minRepeats(decode_type_t::MIRAGE)); } @@ -55,7 +56,9 @@ TEST(TestDecodeMirage, RealExample) { ASSERT_EQ(kMirageBits, irsend.capture.bits); EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits); EXPECT_EQ( - "", + "Model: 1 (KKG9AC1), Power: On, Mode: 2 (Cool), Temp: 25C, " + "Fan: 0 (Auto), Turbo: Off, Sleep: Off, Light: Off, " + "Swing(V): 0 (Off), Clock: 14:16", IRAcUtils::resultAcToString(&irsend.capture)); } @@ -70,13 +73,14 @@ TEST(TestDecodeMirage, SyntheticExample) { irsend.sendMirage(expected); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decode(&irsend.capture)); ASSERT_TRUE(irrecv.decode(&irsend.capture)); ASSERT_EQ(decode_type_t::MIRAGE, irsend.capture.decode_type); ASSERT_EQ(kMirageBits, irsend.capture.bits); EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits); EXPECT_EQ( - "", + "Model: 1 (KKG9AC1), Power: On, Mode: 2 (Cool), Temp: 25C, " + "Fan: 0 (Auto), Turbo: Off, Sleep: Off, Light: Off, " + "Swing(V): 0 (Off), Clock: 14:16", IRAcUtils::resultAcToString(&irsend.capture)); } @@ -119,6 +123,469 @@ TEST(TestDecodeMirage, RealExampleWithDodgyHardwareCapture) { ASSERT_EQ(kMirageBits, irsend.capture.bits); EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits); EXPECT_EQ( - "", + "Model: 1 (KKG9AC1), Power: On, Mode: 2 (Cool), Temp: 25C, " + "Fan: 0 (Auto), Turbo: Off, Sleep: Off, Light: Off, " + "Swing(V): 0 (Off), Clock: 14:16", IRAcUtils::resultAcToString(&irsend.capture)); } + +TEST(TestMirageAcClass, Power) { + IRMirageAc ac(kGpioUnused); + ac.begin(); + + ac.setModel(mirage_ac_remote_model_t::KKG9AC1); + ac.on(); + EXPECT_TRUE(ac.getPower()); + ac.on(); + EXPECT_TRUE(ac.getPower()); + + ac.off(); + EXPECT_FALSE(ac.getPower()); + ac.off(); + EXPECT_FALSE(ac.getPower()); + + ac.setPower(true); + EXPECT_TRUE(ac.getPower()); + + ac.setPower(false); + EXPECT_FALSE(ac.getPower()); + + const uint8_t on[kMirageStateLength] = { + 0x56, 0x75, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x16, 0x14, 0x26}; + ac.setRaw(on); + EXPECT_TRUE(ac.getPower()); + const uint8_t off[kMirageStateLength] = { + 0x56, 0x6C, 0x00, 0x00, 0x21, 0xD8, 0x00, 0x00, + 0x0C, 0x00, 0x0C, 0x2C, 0x23, 0x01, 0x61}; + ac.setRaw(off); + EXPECT_FALSE(ac.getPower()); + + ac.setModel(mirage_ac_remote_model_t::KKG29AC1); + ac.on(); + EXPECT_TRUE(ac.getPower()); + ac.off(); + EXPECT_FALSE(ac.getPower()); + ac.setPower(true); + EXPECT_TRUE(ac.getPower()); + ac.setPower(false); + EXPECT_FALSE(ac.getPower()); +} + +TEST(TestMirageAcClass, OperatingMode) { + IRMirageAc ac(kGpioUnused); + ac.begin(); + + ac.setMode(kMirageAcCool); + EXPECT_EQ(kMirageAcCool, ac.getMode()); + ac.setMode(kMirageAcHeat); + EXPECT_EQ(kMirageAcHeat, ac.getMode()); + ac.setMode(kMirageAcDry); + EXPECT_EQ(kMirageAcDry, ac.getMode()); + ac.setMode(kMirageAcFan); + EXPECT_EQ(kMirageAcFan, ac.getMode()); + ac.setMode(kMirageAcRecycle); + EXPECT_EQ(kMirageAcRecycle, ac.getMode()); + ac.setMode(255); + EXPECT_EQ(kMirageAcCool, ac.getMode()); +} + +TEST(TestMirageAcClass, HumanReadable) { + IRMirageAc ac(kGpioUnused); + ac.begin(); + + // Tests for the KKG9AC1 model. + EXPECT_EQ( + "Model: 1 (KKG9AC1), Power: On, Mode: 2 (Cool), Temp: 16C, " + "Fan: 0 (Auto), Turbo: Off, Sleep: Off, Light: Off, " + "Swing(V): 13 (Auto), Clock: 00:00", + ac.toString()); + // Ref: https://docs.google.com/spreadsheets/d/1Ucu9mOOIIJoWQjUJq_VCvwgV3EwKaRk8K2AuZgccYEk/edit#gid=0&range=C7 + // 0x56710000201A00000C000C26010041 + const uint8_t cool_21c_auto[kMirageStateLength] = { + 0x56, 0x71, 0x00, 0x00, 0x20, 0x1A, 0x00, 0x00, + 0x0C, 0x00, 0x0C, 0x26, 0x01, 0x00, 0x41}; + ac.setRaw(cool_21c_auto); + EXPECT_EQ( + "Model: 1 (KKG9AC1), Power: On, Mode: 2 (Cool), Temp: 21C, " + "Fan: 0 (Auto), Turbo: Off, Sleep: Off, Light: Off, " + "Swing(V): 13 (Auto), Clock: 00:01", + ac.toString()); + + const uint8_t SyntheticExample[kMirageStateLength] = { + 0x56, 0x75, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x16, 0x14, 0x26}; + ac.setRaw(SyntheticExample); + EXPECT_EQ( + "Model: 1 (KKG9AC1), Power: On, Mode: 2 (Cool), Temp: 25C, " + "Fan: 0 (Auto), Turbo: Off, Sleep: Off, Light: Off, " + "Swing(V): 0 (Off), Clock: 14:16", + ac.toString()); + + // Tests for the KKG29AC1 model. + ac.setModel(mirage_ac_remote_model_t::KKG29AC1); + EXPECT_EQ( + "Model: 2 (KKG29AC1), Power: On, Mode: 2 (Cool), Temp: 25C, " + "Fan: 0 (Auto), Turbo: Off, Sleep: Off, Quiet: Off, Light: -, " + "Swing(V): Off, Swing(H): Off, " + "Filter: Off, Clean: -, On Timer: Off, Off Timer: Off, " + "IFeel: Off", + ac.toString()); +} + +TEST(TestMirageAcClass, Temperature) { + IRMirageAc ac(kGpioUnused); + ac.begin(); + + ac.setTemp(0); + EXPECT_EQ(kMirageAcMinTemp, ac.getTemp()); + + ac.setTemp(255); + EXPECT_EQ(kMirageAcMaxTemp, ac.getTemp()); + + ac.setTemp(kMirageAcMinTemp); + EXPECT_EQ(kMirageAcMinTemp, ac.getTemp()); + + ac.setTemp(kMirageAcMaxTemp); + EXPECT_EQ(kMirageAcMaxTemp, ac.getTemp()); + + ac.setTemp(kMirageAcMinTemp - 1); + EXPECT_EQ(kMirageAcMinTemp, ac.getTemp()); + + ac.setTemp(kMirageAcMaxTemp + 1); + EXPECT_EQ(kMirageAcMaxTemp, ac.getTemp()); + + ac.setTemp(17); + EXPECT_EQ(17, ac.getTemp()); + + ac.setTemp(21); + EXPECT_EQ(21, ac.getTemp()); + + ac.setTemp(25); + EXPECT_EQ(25, ac.getTemp()); + + ac.setTemp(30); + EXPECT_EQ(30, ac.getTemp()); +} + +TEST(TestMirageAcClass, FanSpeed) { + IRMirageAc ac(kGpioUnused); + ac.begin(); + + ac.setFan(kMirageAcFanAuto); + EXPECT_EQ(kMirageAcFanAuto, ac.getFan()); + ac.setFan(kMirageAcFanLow); + EXPECT_EQ(kMirageAcFanLow, ac.getFan()); + ac.setFan(kMirageAcFanMed); + EXPECT_EQ(kMirageAcFanMed, ac.getFan()); + ac.setFan(kMirageAcFanHigh); + EXPECT_EQ(kMirageAcFanHigh, ac.getFan()); + + ac.setFan(255); + EXPECT_EQ(kMirageAcFanAuto, ac.getFan()); +} + +TEST(TestMirageAcClass, Turbo) { + IRMirageAc ac(kGpioUnused); + ac.begin(); + + ac.setModel(mirage_ac_remote_model_t::KKG9AC1); + ac.setTurbo(true); + EXPECT_TRUE(ac.getTurbo()); + ac.setTurbo(false); + EXPECT_FALSE(ac.getTurbo()); + ac.setTurbo(true); + EXPECT_TRUE(ac.getTurbo()); + + ac.setModel(mirage_ac_remote_model_t::KKG29AC1); + ac.setTurbo(true); + EXPECT_TRUE(ac.getTurbo()); + ac.setTurbo(false); + EXPECT_FALSE(ac.getTurbo()); + ac.setTurbo(true); + EXPECT_TRUE(ac.getTurbo()); +} + +TEST(TestMirageAcClass, Light) { + IRMirageAc ac(kGpioUnused); + ac.begin(); + + ac.setModel(mirage_ac_remote_model_t::KKG9AC1); + ac.setLight(true); + EXPECT_TRUE(ac.getLight()); + ac.setLight(false); + EXPECT_FALSE(ac.getLight()); + ac.setLight(true); + EXPECT_TRUE(ac.getLight()); + + ac.setModel(mirage_ac_remote_model_t::KKG29AC1); + ac.setLight(true); + EXPECT_TRUE(ac.getLight()); + ac.setLight(false); + EXPECT_FALSE(ac.getLight()); + ac.setLight(true); + EXPECT_TRUE(ac.getLight()); +} + +TEST(TestMirageAcClass, Sleep) { + IRMirageAc ac(kGpioUnused); + ac.begin(); + + ac.setModel(mirage_ac_remote_model_t::KKG9AC1); + ac.setSleep(true); + EXPECT_TRUE(ac.getSleep()); + ac.setSleep(false); + EXPECT_FALSE(ac.getSleep()); + ac.setSleep(true); + EXPECT_TRUE(ac.getSleep()); + + ac.setModel(mirage_ac_remote_model_t::KKG29AC1); + ac.setSleep(true); + EXPECT_TRUE(ac.getSleep()); + ac.setSleep(false); + EXPECT_FALSE(ac.getSleep()); + ac.setSleep(true); + EXPECT_TRUE(ac.getSleep()); +} + +TEST(TestMirageAcClass, Clock) { + IRMirageAc ac(kGpioUnused); + ac.begin(); + + ac.setModel(mirage_ac_remote_model_t::KKG9AC1); // This model supports time. + ac.setClock(0); + EXPECT_EQ(0, ac.getClock()); + ac.setClock(12 * 60 * 60 + 30 * 60 + 59); // aka. 12:30:59 + EXPECT_EQ(12 * 60 * 60 + 30 * 60 + 59, ac.getClock()); + ac.setClock(23 * 60 * 60 + 59 * 60 + 59); // aka. 23:59:59 + EXPECT_EQ(23 * 60 * 60 + 59 * 60 + 59, ac.getClock()); + ac.setClock(24 * 60 * 60); // aka. 24:00:00 + EXPECT_EQ(23 * 60 * 60 + 59 * 60 + 59, ac.getClock()); // aka. 23:59:59 + + ac.setModel(mirage_ac_remote_model_t::KKG29AC1); // This model has no clock. + EXPECT_EQ(0, ac.getClock()); + ac.setClock(12 * 60 * 60 + 30 * 60 + 59); // aka. 12:30:59 + EXPECT_EQ(0, ac.getClock()); +} + +TEST(TestMirageAcClass, Checksums) { + IRMirageAc ac(kGpioUnused); + ac.begin(); + + const uint8_t SyntheticExample[kMirageStateLength] = { + 0x56, 0x75, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x16, 0x14, 0x26}; + EXPECT_TRUE(IRMirageAc::validChecksum(SyntheticExample)); + EXPECT_EQ(0x26, IRMirageAc::calculateChecksum(SyntheticExample)); +} + +TEST(TestMirageAcClass, SwingV) { + IRMirageAc ac(kGpioUnused); + ac.begin(); + + // Set the model to one with full swingv support. + ac.setModel(mirage_ac_remote_model_t::KKG9AC1); + + ac.setSwingV(kMirageAcSwingVAuto); + EXPECT_EQ(kMirageAcSwingVAuto, ac.getSwingV()); + + ac.setSwingV(kMirageAcSwingVHigh); + EXPECT_EQ(kMirageAcSwingVHigh, ac.getSwingV()); + + ac.setSwingV(0xFF); + EXPECT_EQ(kMirageAcSwingVAuto, ac.getSwingV()); + + ac.setSwingV(kMirageAcSwingVLowest); + EXPECT_EQ(kMirageAcSwingVLowest, ac.getSwingV()); + + ac.setSwingV(kMirageAcSwingVLowest - 1); + EXPECT_EQ(kMirageAcSwingVAuto, ac.getSwingV()); + + // Set the model to one with limited swingv support. + ac.setModel(mirage_ac_remote_model_t::KKG29AC1); + + ac.setSwingV(kMirageAcSwingVAuto); + EXPECT_EQ(kMirageAcSwingVAuto, ac.getSwingV()); + ac.setSwingV(kMirageAcSwingVOff); + EXPECT_EQ(kMirageAcSwingVOff, ac.getSwingV()); + ac.setSwingV(kMirageAcSwingVHigh); + EXPECT_EQ(kMirageAcSwingVAuto, ac.getSwingV()); + ac.setSwingV(0xFF); + EXPECT_EQ(kMirageAcSwingVAuto, ac.getSwingV()); + ac.setSwingV(kMirageAcSwingVOff); + EXPECT_EQ(kMirageAcSwingVOff, ac.getSwingV()); +} + +TEST(TestMirageAcClass, SwingH) { + IRMirageAc ac(kGpioUnused); + ac.begin(); + + ac.setModel(mirage_ac_remote_model_t::KKG9AC1); + ac.setSwingH(true); + EXPECT_FALSE(ac.getSwingH()); + ac.setSwingH(false); + EXPECT_FALSE(ac.getSwingH()); + ac.setSwingH(true); + EXPECT_FALSE(ac.getSwingH()); + + ac.setModel(mirage_ac_remote_model_t::KKG29AC1); + ac.setSwingH(true); + EXPECT_TRUE(ac.getSwingH()); + ac.setSwingH(false); + EXPECT_FALSE(ac.getSwingH()); + ac.setSwingH(true); + EXPECT_TRUE(ac.getSwingH()); +} + +TEST(TestMirageAcClass, Filter) { + IRMirageAc ac(kGpioUnused); + ac.begin(); + + ac.setModel(mirage_ac_remote_model_t::KKG9AC1); // No Support + ac.setFilter(true); + EXPECT_FALSE(ac.getFilter()); + ac.setFilter(false); + EXPECT_FALSE(ac.getFilter()); + ac.setFilter(true); + EXPECT_FALSE(ac.getFilter()); + + ac.setModel(mirage_ac_remote_model_t::KKG29AC1); // Supported + ac.setFilter(true); + EXPECT_TRUE(ac.getFilter()); + ac.setFilter(false); + EXPECT_FALSE(ac.getFilter()); + ac.setFilter(true); + EXPECT_TRUE(ac.getFilter()); +} + +TEST(TestMirageAcClass, Quiet) { + IRMirageAc ac(kGpioUnused); + ac.begin(); + + ac.setModel(mirage_ac_remote_model_t::KKG9AC1); // No Support + ac.setQuiet(true); + EXPECT_FALSE(ac.getQuiet()); + ac.setQuiet(false); + EXPECT_FALSE(ac.getQuiet()); + ac.setQuiet(true); + EXPECT_FALSE(ac.getQuiet()); + + ac.setModel(mirage_ac_remote_model_t::KKG29AC1); // Supported + ac.setQuiet(true); + EXPECT_TRUE(ac.getQuiet()); + ac.setQuiet(false); + EXPECT_FALSE(ac.getQuiet()); + ac.setQuiet(true); + EXPECT_TRUE(ac.getQuiet()); +} + +TEST(TestMirageAcClass, CleanToggle) { + IRMirageAc ac(kGpioUnused); + ac.begin(); + + ac.setModel(mirage_ac_remote_model_t::KKG9AC1); + ac.setCleanToggle(true); + EXPECT_FALSE(ac.getCleanToggle()); + ac.setCleanToggle(false); + EXPECT_FALSE(ac.getCleanToggle()); + ac.setCleanToggle(true); + EXPECT_FALSE(ac.getCleanToggle()); + + ac.setModel(mirage_ac_remote_model_t::KKG29AC1); + ac.setCleanToggle(true); + EXPECT_TRUE(ac.getCleanToggle()); + ac.setCleanToggle(false); + EXPECT_FALSE(ac.getCleanToggle()); + ac.setCleanToggle(true); + EXPECT_TRUE(ac.getCleanToggle()); + ac.send(); // Should be reset when sent. + EXPECT_FALSE(ac.getCleanToggle()); +} + +TEST(TestMirageAcClass, Timers) { + IRMirageAc ac(kGpioUnused); + ac.begin(); + + ac.setModel(mirage_ac_remote_model_t::KKG9AC1); // No timer support + EXPECT_EQ(0, ac.getOnTimer()); + EXPECT_EQ(0, ac.getOffTimer()); + ac.setOnTimer(12 * 60 + 37); // 12:37 + EXPECT_EQ(0, ac.getOnTimer()); + EXPECT_EQ(0, ac.getOffTimer()); + ac.setOffTimer(17 * 60 + 5); // 17:05 + EXPECT_EQ(0, ac.getOnTimer()); + EXPECT_EQ(0, ac.getOffTimer()); + + ac.setModel(mirage_ac_remote_model_t::KKG29AC1); // Timer supported + EXPECT_EQ(0, ac.getOnTimer()); + EXPECT_EQ(0, ac.getOffTimer()); + + ac.setOnTimer(12 * 60 + 37); // 12:37 + EXPECT_EQ(12 * 60 + 37, ac.getOnTimer()); + EXPECT_EQ(0, ac.getOffTimer()); + + ac.setOffTimer(17 * 60 + 5); // 17:05 + EXPECT_EQ(17 * 60 + 5, ac.getOffTimer()); + EXPECT_EQ(12 * 60 + 37, ac.getOnTimer()); + ac.setOnTimer(0); // Off/Disabled + EXPECT_EQ(0, ac.getOnTimer()); + EXPECT_EQ(17 * 60 + 5, ac.getOffTimer()); + ac.setOffTimer(0); // Off/Disabled + EXPECT_EQ(0, ac.getOffTimer()); + EXPECT_EQ(0, ac.getOnTimer()); + + ac.setOnTimer(12 * 60 + 37); // 12:37 + ac.setOffTimer(17 * 60 + 5); // 17:05 + ac.setModel(mirage_ac_remote_model_t::KKG9AC1); // No timer support + EXPECT_EQ(0, ac.getOffTimer()); + EXPECT_EQ(0, ac.getOnTimer()); +} + +TEST(TestMirageAcClass, IFeelAndSensorTemp) { + IRMirageAc ac(kGpioUnused); + ac.begin(); + + ac.setModel(mirage_ac_remote_model_t::KKG9AC1); // No support + EXPECT_FALSE(ac.getIFeel()); + EXPECT_EQ(0, ac.getSensorTemp()); + ac.setIFeel(true); + EXPECT_FALSE(ac.getIFeel()); + EXPECT_EQ(0, ac.getSensorTemp()); + ac.setSensorTemp(20); // 20C + EXPECT_FALSE(ac.getIFeel()); + EXPECT_EQ(0, ac.getSensorTemp()); + + ac.setModel(mirage_ac_remote_model_t::KKG29AC1); // Supported + EXPECT_FALSE(ac.getIFeel()); + EXPECT_EQ(0, ac.getSensorTemp()); + ac.setIFeel(true); + EXPECT_TRUE(ac.getIFeel()); + EXPECT_EQ(0, ac.getSensorTemp()); + ac.setSensorTemp(25); // 25C + EXPECT_TRUE(ac.getIFeel()); + EXPECT_EQ(25, ac.getSensorTemp()); + ac.setIFeel(false); + EXPECT_FALSE(ac.getIFeel()); +} + +TEST(TestMirageAcClass, getModel) { + IRMirageAc ac(kGpioUnused); + ac.begin(); + const uint8_t KKG9AC1[kMirageStateLength] = { + 0x56, 0x6C, 0x00, 0x00, 0x20, 0xD8, 0x00, 0x00, + 0x0C, 0x32, 0x0B, 0x00, 0x32, 0x0F, 0x64}; + EXPECT_EQ(mirage_ac_remote_model_t::KKG9AC1, IRMirageAc::getModel(KKG9AC1)); + + // https://github.com/crankyoldgit/IRremoteESP8266/issues/1573#issuecomment-955722044 + const uint8_t KKG29AC1[kMirageStateLength] = { + 0x56, 0x74, 0x00, 0x00, 0x12, 0x00, 0x40, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D}; + EXPECT_EQ(mirage_ac_remote_model_t::KKG29AC1, IRMirageAc::getModel(KKG29AC1)); + + // https://github.com/crankyoldgit/IRremoteESP8266/issues/1573#issuecomment-962362540 + const uint8_t KKG29AC1_2[kMirageStateLength] = { + 0x56, 0x72, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19}; + EXPECT_EQ(mirage_ac_remote_model_t::KKG29AC1, + IRMirageAc::getModel(KKG29AC1_2)); +} diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Rhoss_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Rhoss_test.cpp new file mode 100644 index 000000000..855b9a48c --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Rhoss_test.cpp @@ -0,0 +1,396 @@ +// Copyright 2021 Tom Rosenback + +#include "IRac.h" +#include "ir_Rhoss.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "IRutils.h" +#include "gtest/gtest.h" + +TEST(TestUtils, Housekeeping) { + ASSERT_EQ("RHOSS", typeToString(decode_type_t::RHOSS)); + ASSERT_EQ(decode_type_t::RHOSS, strToDecodeType("RHOSS")); + ASSERT_TRUE(hasACState(decode_type_t::RHOSS)); + ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::RHOSS)); +} + +// Test sending typical data only. +TEST(TestSendRhoss, SendDataOnly) { + IRsendTest irsend(kGpioUnused); + irsend.begin(); + + uint8_t expectedState[kRhossStateLength] = { + 0xAA, 0x05, 0x60, 0x00, 0x50, 0x80, 0x54, 0x00, 0x00, 0x00, 0x00, 0x33 }; + + irsend.reset(); + irsend.sendRhoss(expectedState); + + EXPECT_EQ( + "f38000d50" + "m3042s4248" + "m648s457m648s1545m648s457m648s1545m648s457m648s1545m648s457m648s1545" + "m648s1545m648s457m648s1545m648s457m648s457m648s457m648s457m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s1545m648s1545m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s457" + "m648s457m648s457m648s457m648s457m648s1545m648s457m648s1545m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s1545" + "m648s457m648s457m648s1545m648s457m648s1545m648s457m648s1545m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s457" + "m648s1545m648s1545m648s457m648s457m648s1545m648s1545m648s457m648s457" + "m648s457m648" + "s100000", + irsend.outputStr()); +} + +// Test send typical data with repeats +TEST(TestSendRhoss, SendWithRepeats) { + IRsendTest irsend(kGpioUnused); + irsend.begin(); + + irsend.reset(); + +uint8_t expectedState[kRhossStateLength] = { + 0xAA, 0x05, 0x60, 0x00, 0x50, 0x80, 0x54, 0x00, 0x00, 0x00, 0x00, 0x33 }; + + irsend.sendRhoss(expectedState, kRhossStateLength, 0); // 0 repeats. + EXPECT_EQ( + "f38000d50" + "m3042s4248" + "m648s457m648s1545m648s457m648s1545m648s457m648s1545m648s457m648s1545" + "m648s1545m648s457m648s1545m648s457m648s457m648s457m648s457m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s1545m648s1545m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s457" + "m648s457m648s457m648s457m648s457m648s1545m648s457m648s1545m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s1545" + "m648s457m648s457m648s1545m648s457m648s1545m648s457m648s1545m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s457" + "m648s1545m648s1545m648s457m648s457m648s1545m648s1545m648s457m648s457" + "m648s457m648" + "s100000", + irsend.outputStr()); + + irsend.sendRhoss(expectedState, kRhossStateLength, 2); // 2 repeats. + EXPECT_EQ( + "f38000d50" + "m3042s4248" + "m648s457m648s1545m648s457m648s1545m648s457m648s1545m648s457m648s1545" + "m648s1545m648s457m648s1545m648s457m648s457m648s457m648s457m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s1545m648s1545m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s457" + "m648s457m648s457m648s457m648s457m648s1545m648s457m648s1545m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s1545" + "m648s457m648s457m648s1545m648s457m648s1545m648s457m648s1545m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s457" + "m648s1545m648s1545m648s457m648s457m648s1545m648s1545m648s457m648s457" + "m648s457m648" + "s100000" + "m3042s4248" + "m648s457m648s1545m648s457m648s1545m648s457m648s1545m648s457m648s1545" + "m648s1545m648s457m648s1545m648s457m648s457m648s457m648s457m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s1545m648s1545m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s457" + "m648s457m648s457m648s457m648s457m648s1545m648s457m648s1545m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s1545" + "m648s457m648s457m648s1545m648s457m648s1545m648s457m648s1545m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s457" + "m648s1545m648s1545m648s457m648s457m648s1545m648s1545m648s457m648s457" + "m648s457m648" + "s100000" + "m3042s4248" + "m648s457m648s1545m648s457m648s1545m648s457m648s1545m648s457m648s1545" + "m648s1545m648s457m648s1545m648s457m648s457m648s457m648s457m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s1545m648s1545m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s457" + "m648s457m648s457m648s457m648s457m648s1545m648s457m648s1545m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s1545" + "m648s457m648s457m648s1545m648s457m648s1545m648s457m648s1545m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s457" + "m648s457m648s457m648s457m648s457m648s457m648s457m648s457m648s457" + "m648s1545m648s1545m648s457m648s457m648s1545m648s1545m648s457m648s457" + "m648s457m648" + "s100000", + irsend.outputStr()); +} + +// Test send raw data +TEST(TestSendRhoss, RawData) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + irsend.begin(); + irsend.reset(); + + // Power on, mode cool, temp 20, fan auto, swing off + const uint16_t rawData[197] = { + 3044, 4248, + 648, 458, 650, 1540, 646, 458, 650, 1538, + 650, 458, 650, 1538, 650, 458, 650, 1540, // byte 0 + 648, 458, 650, 458, 650, 1540, 646, 484, + 624, 456, 650, 456, 650, 456, 650, 456, // byte 1 + 650, 456, 650, 456, 650, 456, 650, 456, + 650, 458, 650, 1540, 650, 1538, 650, 456, // byte 2 + 650, 456, 650, 456, 650, 456, 650, 458, + 650, 456, 650, 456, 650, 456, 650, 458, // byte 3 + 650, 458, 650, 456, 650, 458, 650, 458, + 650, 458, 650, 1538, 650, 458, 650, 458, // byte 4 + 650, 458, 648, 458, 674, 434, 648, 458, + 672, 434, 648, 458, 650, 458, 648, 1540, // byte 5 + 672, 434, 650, 458, 672, 1518, 644, 488, + 622, 1540, 644, 464, 672, 1516, 672, 434, // byte 6 + 672, 434, 672, 434, 650, 458, 648, 458, + 672, 434, 674, 434, 672, 434, 650, 458, // byte 7 + 672, 434, 648, 458, 650, 458, 672, 434, + 672, 436, 648, 458, 648, 456, 650, 458, // byte 8 + 650, 458, 650, 456, 674, 434, 650, 458, + 650, 456, 650, 458, 674, 432, 650, 458, // byte 9 + 650, 456, 650, 456, 650, 458, 648, 458, + 674, 432, 650, 456, 674, 434, 650, 458, // byte 10 + 650, 458, 650, 1538, 650, 458, 650, 458, + 650, 456, 650, 458, 650, 456, 650, 458, // byte 11 + 650, 456, + 650 }; // UNKNOWN 93E7BDB2 + + irsend.sendRaw(rawData, 197, 38); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(RHOSS, irsend.capture.decode_type); + EXPECT_EQ(kRhossBits, irsend.capture.bits); + + uint8_t expected[kRhossStateLength] = { + 0xAA, 0x04, 0x60, 0x00, 0x20, 0x80, 0x54, 0x00, 0x00, 0x00, 0x00, 0x02 }; + EXPECT_STATE_EQ(expected, irsend.capture.state, kRhossBits); + + EXPECT_EQ( + "Power: On, Mode: 2 (Cool), Temp: 20C, Fan: 0 (Auto), Swing(V): Off", + IRAcUtils::resultAcToString(&irsend.capture)); + + stdAc::state_t r, p; + ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &r, &p)); +} + +// Test synthetic decode +TEST(TestDecodeRhoss, SyntheticSelfDecode) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(0); + IRRhossAc ac(0); + + uint8_t expectedState[kRhossStateLength] = { + 0xAA, 0x05, 0x60, 0x00, 0x50, 0x80, 0x54, 0x00, 0x00, 0x00, 0x00, 0x33 }; + + irsend.begin(); + irsend.reset(); + irsend.sendRhoss(expectedState); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(RHOSS, irsend.capture.decode_type); + EXPECT_EQ(kRhossBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + ac.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: On, Mode: 5 (Auto), Temp: 21C, Fan: 0 (Auto), Swing(V): Off", + ac.toString()); +} + +// Test strict decoding +TEST(TestDecodeRhoss, StrictDecode) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(0); + IRRhossAc ac(0); + + uint8_t expectedState[kRhossStateLength] = { + 0xAA, 0x05, 0x60, 0x00, 0x50, 0x80, 0x54, 0x00, 0x00, 0x00, 0x00, 0x33 }; + + irsend.begin(); + irsend.reset(); + irsend.sendRhoss(expectedState); + irsend.makeDecodeResult(); + ASSERT_TRUE( + irrecv.decodeRhoss(&irsend.capture, + kStartOffset, kRhossBits, true)); + EXPECT_EQ(RHOSS, irsend.capture.decode_type); + EXPECT_EQ(kRhossBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + ac.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: On, Mode: 5 (Auto), Temp: 21C, Fan: 0 (Auto), Swing(V): Off", + ac.toString()); +} + +// Tests for IRRhossAc class. + +TEST(TestRhossAcClass, Power) { + IRRhossAc ac(0); + ac.begin(); + + ac.on(); + EXPECT_TRUE(ac.getPower()); + + ac.off(); + EXPECT_FALSE(ac.getPower()); + + ac.setPower(true); + EXPECT_TRUE(ac.getPower()); + + ac.setPower(false); + EXPECT_FALSE(ac.getPower()); +} + +TEST(TestRhossAcClass, Temperature) { + IRRhossAc ac(0); + ac.begin(); + + ac.setTemp(0); + EXPECT_EQ(kRhossTempMin, ac.getTemp()); + + ac.setTemp(255); + EXPECT_EQ(kRhossTempMax, ac.getTemp()); + + ac.setTemp(kRhossTempMin); + EXPECT_EQ(kRhossTempMin, ac.getTemp()); + + ac.setTemp(kRhossTempMax); + EXPECT_EQ(kRhossTempMax, ac.getTemp()); + + ac.setTemp(kRhossTempMin - 1); + EXPECT_EQ(kRhossTempMin, ac.getTemp()); + + ac.setTemp(kRhossTempMax + 1); + EXPECT_EQ(kRhossTempMax, ac.getTemp()); + + ac.setTemp(17); + EXPECT_EQ(17, ac.getTemp()); + + ac.setTemp(21); + EXPECT_EQ(21, ac.getTemp()); + + ac.setTemp(25); + EXPECT_EQ(25, ac.getTemp()); + + ac.setTemp(29); + EXPECT_EQ(29, ac.getTemp()); +} + + +TEST(TestRhossAcClass, OperatingMode) { + IRRhossAc ac(0); + ac.begin(); + + ac.setMode(kRhossModeAuto); + EXPECT_EQ(kRhossModeAuto, ac.getMode()); + + ac.setMode(kRhossModeCool); + EXPECT_EQ(kRhossModeCool, ac.getMode()); + + ac.setMode(kRhossModeHeat); + EXPECT_EQ(kRhossModeHeat, ac.getMode()); + + ac.setMode(kRhossModeDry); + EXPECT_EQ(kRhossModeDry, ac.getMode()); + + ac.setMode(kRhossModeFan); + EXPECT_EQ(kRhossModeFan, ac.getMode()); + + ac.setMode(kRhossModeAuto + 1); + EXPECT_EQ(kRhossDefaultMode, ac.getMode()); + + ac.setMode(255); + EXPECT_EQ(kRhossDefaultMode, ac.getMode()); +} + +TEST(TestRhossAcClass, FanSpeed) { + IRRhossAc ac(0); + ac.begin(); + + ac.setFan(0); + EXPECT_EQ(kRhossFanAuto, ac.getFan()); + + ac.setFan(255); + EXPECT_EQ(kRhossFanAuto, ac.getFan()); + + ac.setFan(kRhossFanMax); + EXPECT_EQ(kRhossFanMax, ac.getFan()); + + ac.setFan(kRhossFanMax + 1); + EXPECT_EQ(kRhossFanAuto, ac.getFan()); + + ac.setFan(kRhossFanMax - 1); + EXPECT_EQ(kRhossFanMax - 1, ac.getFan()); + + ac.setFan(1); + EXPECT_EQ(1, ac.getFan()); + + ac.setFan(1); + EXPECT_EQ(1, ac.getFan()); + + ac.setFan(3); + EXPECT_EQ(3, ac.getFan()); +} + +TEST(TestRhossAcClass, Swing) { + IRRhossAc ac(0); + ac.begin(); + + ac.setSwing(false); + EXPECT_FALSE(ac.getSwing()); + + ac.setSwing(true); + EXPECT_TRUE(ac.getSwing()); +} + +TEST(TestRhossAcClass, Checksums) { + uint8_t state[kRhossStateLength] = { + 0xAA, 0x05, 0x60, 0x00, 0x50, 0x80, 0x54, 0x00, 0x00, 0x00, 0x00, 0x33 }; + + ASSERT_EQ(0x33, IRRhossAc::calcChecksum(state)); + EXPECT_TRUE(IRRhossAc::validChecksum(state)); + // Change the array so the checksum is invalid. + state[0] ^= 0xFF; + EXPECT_FALSE(IRRhossAc::validChecksum(state)); + // Restore the previous change, and change another byte. + state[0] ^= 0xFF; + state[4] ^= 0xFF; + EXPECT_FALSE(IRRhossAc::validChecksum(state)); + state[4] ^= 0xFF; + EXPECT_TRUE(IRRhossAc::validChecksum(state)); + + // Additional known good states. + uint8_t knownGood1[kRhossStateLength] = { + 0xAA, 0x06, 0x60, 0x00, 0x50, 0x80, 0x54, 0x00, 0x00, 0x00, 0x00, 0x34 }; + EXPECT_TRUE(IRRhossAc::validChecksum(knownGood1)); + ASSERT_EQ(0x34, IRRhossAc::calcChecksum(knownGood1)); + + uint8_t knownGood2[kRhossStateLength] = { + 0xAA, 0x07, 0x60, 0x00, 0x50, 0x80, 0x54, 0x00, 0x00, 0x00, 0x00, 0x35 }; + EXPECT_TRUE(IRRhossAc::validChecksum(knownGood2)); + ASSERT_EQ(0x35, IRRhossAc::calcChecksum(knownGood2)); + + uint8_t knownGood3[kRhossStateLength] = { + 0xAA, 0x07, 0x60, 0x00, 0x53, 0x80, 0x54, 0x00, 0x00, 0x00, 0x00, 0x38 }; + EXPECT_TRUE(IRRhossAc::validChecksum(knownGood3)); + ASSERT_EQ(0x38, IRRhossAc::calcChecksum(knownGood3)); + + // Validate calculation of checksum, + // same as knownGood3 except for the checksum. + uint8_t knownBad[kRhossStateLength] = { + 0xAA, 0x07, 0x60, 0x00, 0x53, 0x80, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00 }; + EXPECT_FALSE(IRRhossAc::validChecksum(knownBad)); + IRRhossAc ac(0); + ac.setRaw(knownBad); + EXPECT_STATE_EQ(knownGood3, ac.getRaw(), kRhossBits); +} diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Samsung_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Samsung_test.cpp index a4e0503cd..061067421 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Samsung_test.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Samsung_test.cpp @@ -426,16 +426,37 @@ TEST(TestIRSamsungAcClass, SetAndGetPower) { TEST(TestIRSamsungAcClass, SetAndGetSwing) { IRSamsungAc ac(kGpioUnused); + + // Vertical ac.setSwing(true); EXPECT_TRUE(ac.getSwing()); + EXPECT_FALSE(ac.getSwingH()); ac.setSwing(false); EXPECT_FALSE(ac.getSwing()); + EXPECT_FALSE(ac.getSwingH()); ac.setSwing(true); EXPECT_TRUE(ac.getSwing()); + EXPECT_FALSE(ac.getSwingH()); + // Horizontal + ac.setSwingH(true); + EXPECT_TRUE(ac.getSwing()); + EXPECT_TRUE(ac.getSwingH()); + ac.setSwingH(false); + EXPECT_TRUE(ac.getSwing()); + EXPECT_FALSE(ac.getSwingH()); + ac.setSwingH(true); + EXPECT_TRUE(ac.getSwing()); + EXPECT_TRUE(ac.getSwingH()); + + ac.setSwing(false); + EXPECT_FALSE(ac.getSwing()); + EXPECT_TRUE(ac.getSwingH()); + ac.setSwingH(false); + EXPECT_FALSE(ac.getSwing()); + EXPECT_FALSE(ac.getSwingH()); // Real examples from: // https://github.com/crankyoldgit/IRremoteESP8266/issues/505#issuecomment-424036602 - // TODO(Hollako): Explain why state[9] lowest bit changes between on and off. const uint8_t expected_off[kSamsungAcStateLength] = { 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, 0x01, 0xE2, 0xFE, 0x71, 0x80, 0x11, 0xF0}; @@ -576,14 +597,24 @@ TEST(TestIRSamsungAcClass, SetAndGetPowerful) { EXPECT_EQ(kSamsungAcFanTurbo, ac.getFan()); ac.setPowerful(false); EXPECT_FALSE(ac.getPowerful()); - EXPECT_EQ(kSamsungAcFanAuto, ac.getFan()); - // Breeze and Powerful/Turbo are mutually exclusive. + // Breeze, Econo, and Powerful/Turbo are mutually exclusive. ac.setPowerful(true); EXPECT_TRUE(ac.getPowerful()); + EXPECT_FALSE(ac.getBreeze()); + EXPECT_FALSE(ac.getEcono()); ac.setBreeze(true); EXPECT_TRUE(ac.getBreeze()); EXPECT_FALSE(ac.getPowerful()); + EXPECT_FALSE(ac.getEcono()); + ac.setEcono(true); + EXPECT_TRUE(ac.getEcono()); + EXPECT_FALSE(ac.getBreeze()); + EXPECT_FALSE(ac.getPowerful()); + ac.setPowerful(true); + EXPECT_TRUE(ac.getPowerful()); + EXPECT_FALSE(ac.getBreeze()); + EXPECT_FALSE(ac.getEcono()); // Actual powerful on & off states from: // https://github.com/crankyoldgit/IRremoteESP8266/issues/734#issuecomment-500120270 @@ -594,9 +625,10 @@ TEST(TestIRSamsungAcClass, SetAndGetPowerful) { EXPECT_TRUE(ac.getPowerful()); EXPECT_EQ(kSamsungAcFanTurbo, ac.getFan()); EXPECT_EQ( - "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 7 (Turbo), Swing: Off, " - "Beep: Off, Clean: Off, Quiet: Off, Powerful: On, Breeze: Off, " - "Light: On, Ion: Off", + "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 7 (Turbo), " + "Swing(V): Off, Swing(H): Off, " + "Beep: -, Clean: -, Quiet: Off, Powerful: On, " + "Econo: Off, Breeze: Off, Light: On, Ion: Off", ac.toString()); uint8_t off[kSamsungAcStateLength] = { @@ -606,9 +638,10 @@ TEST(TestIRSamsungAcClass, SetAndGetPowerful) { EXPECT_FALSE(ac.getPowerful()); EXPECT_NE(kSamsungAcFanTurbo, ac.getFan()); EXPECT_EQ( - "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 0 (Auto), Swing: Off, " - "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Breeze: Off, " - "Light: On, Ion: Off", + "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 0 (Auto), " + "Swing(V): Off, Swing(H): Off, " + "Beep: -, Clean: -, Quiet: Off, Powerful: Off, " + "Econo: Off, Breeze: Off, Light: On, Ion: Off", ac.toString()); } @@ -633,6 +666,44 @@ TEST(TestIRSamsungAcClass, QuietAndPowerfulAreMutuallyExclusive) { EXPECT_NE(kSamsungAcFanTurbo, ac.getFan()); } +TEST(TestIRSamsungAcClass, SetAndGetEcono) { + IRSamsungAc ac(kGpioUnused); + ac.begin(); + EXPECT_FALSE(ac.getEcono()); + ac.setFan(kSamsungAcFanMed); + ac.setSwing(false); + ac.setEcono(true); + EXPECT_TRUE(ac.getEcono()); + EXPECT_FALSE(ac.getBreeze()); + EXPECT_FALSE(ac.getPowerful()); + EXPECT_TRUE(ac.getSwing()); // Econo turns on swingv. + EXPECT_EQ(kSamsungAcFanAuto, ac.getFan()); // And sets the fan to Auto. + ac.setEcono(false); + EXPECT_FALSE(ac.getEcono()); + EXPECT_FALSE(ac.getBreeze()); + EXPECT_FALSE(ac.getPowerful()); + + // Breeze, Econo, and Powerful/Turbo are mutually exclusive. + // But that is tested in `SetAndGetPowerful` + + // Actual econo on state from: + // https://cryptpad.fr/sheet/#/2/sheet/view/r9k8pmELYEjLyC71cD7EsThEYgKGLJygREZ5pVfNkS8/ + // Row: 33 + uint8_t on[kSamsungAcStateLength] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, + 0x01, 0xD2, 0xAE, 0x7F, 0x80, 0x11, 0xF0}; + ac.setRaw(on, kSamsungAcStateLength); + EXPECT_TRUE(ac.getEcono()); + EXPECT_TRUE(ac.getSwing()); + EXPECT_EQ(kSamsungAcFanAuto, ac.getFan()); + EXPECT_EQ( + "Power: On, Mode: 1 (Cool), Temp: 24C, Fan: 0 (Auto), " + "Swing(V): On, Swing(H): Off, Beep: -, Clean: -, " + "Quiet: Off, Powerful: Off, Econo: On, Breeze: Off, " + "Light: On, Ion: Off", + ac.toString()); +} + TEST(TestIRSamsungAcClass, ChecksumCalculation) { IRSamsungAc ac(kGpioUnused); @@ -668,9 +739,10 @@ TEST(TestIRSamsungAcClass, ChecksumCalculation) { TEST(TestIRSamsungAcClass, HumanReadable) { IRSamsungAc ac(kGpioUnused); EXPECT_EQ( - "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 2 (Low), Swing: On, " - "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Breeze: Off, " - "Light: On, Ion: Off", + "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 2 (Low), " + "Swing(V): On, Swing(H): Off, " + "Beep: -, Clean: -, Quiet: Off, Powerful: Off, Econo: Off, " + "Breeze: Off, Light: On, Ion: Off", ac.toString()); ac.setTemp(kSamsungAcMaxTemp); ac.setMode(kSamsungAcHeat); @@ -680,28 +752,32 @@ TEST(TestIRSamsungAcClass, HumanReadable) { ac.setBeep(true); ac.setClean(true); EXPECT_EQ( - "Power: Off, Mode: 4 (Heat), Temp: 30C, Fan: 5 (High), Swing: Off, " - "Beep: On, Clean: On, Quiet: Off, Powerful: Off, Breeze: Off, " - "Light: On, Ion: Off", + "Power: Off, Mode: 4 (Heat), Temp: 30C, Fan: 5 (High), " + "Swing(V): Off, Swing(H): Off, " + "Beep: Toggle, Clean: Toggle, Quiet: Off, Powerful: Off, Econo: Off, " + "Breeze: Off, Light: On, Ion: Off", ac.toString()); ac.setQuiet(true); EXPECT_EQ( - "Power: Off, Mode: 4 (Heat), Temp: 30C, Fan: 0 (Auto), Swing: Off, " - "Beep: On, Clean: On, Quiet: On, Powerful: Off, Breeze: Off, " + "Power: Off, Mode: 4 (Heat), Temp: 30C, Fan: 0 (Auto), " + "Swing(V): Off, Swing(H): Off, Beep: Toggle, " + "Clean: Toggle, Quiet: On, Powerful: Off, Econo: Off, Breeze: Off, " "Light: On, Ion: Off", ac.toString()); ac.setQuiet(false); ac.setPowerful(true); EXPECT_EQ( - "Power: Off, Mode: 4 (Heat), Temp: 30C, Fan: 7 (Turbo), Swing: Off, " - "Beep: On, Clean: On, Quiet: Off, Powerful: On, Breeze: Off, " + "Power: Off, Mode: 4 (Heat), Temp: 30C, Fan: 7 (Turbo), " + "Swing(V): Off, Swing(H): Off, Beep: Toggle, " + "Clean: Toggle, Quiet: Off, Powerful: On, Econo: Off, Breeze: Off, " "Light: On, Ion: Off", ac.toString()); ac.setIon(true); ac.setDisplay(false); EXPECT_EQ( - "Power: Off, Mode: 4 (Heat), Temp: 30C, Fan: 7 (Turbo), Swing: Off, " - "Beep: On, Clean: On, Quiet: Off, Powerful: On, Breeze: Off, " + "Power: Off, Mode: 4 (Heat), Temp: 30C, Fan: 7 (Turbo), " + "Swing(V): Off, Swing(H): Off, Beep: Toggle, " + "Clean: Toggle, Quiet: Off, Powerful: On, Econo: Off, Breeze: Off, " "Light: Off, Ion: On", ac.toString()); } @@ -802,9 +878,10 @@ TEST(TestDecodeSamsungAC, DecodeRealExample) { IRSamsungAc ac(kGpioUnused); ac.setRaw(irsend.capture.state); EXPECT_EQ( - "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 2 (Low), Swing: On, " - "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Breeze: Off, " - "Light: On, Ion: Off", + "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 2 (Low), " + "Swing(V): On, Swing(H): Off, " + "Beep: -, Clean: -, Quiet: Off, Powerful: Off, " + "Econo: Off, Breeze: Off, Light: On, Ion: Off", ac.toString()); } @@ -852,9 +929,10 @@ TEST(TestDecodeSamsungAC, DecodeRealExample2) { IRSamsungAc ac(kGpioUnused); ac.setRaw(irsend.capture.state); EXPECT_EQ( - "Power: On, Mode: 1 (Cool), Temp: 24C, Fan: 0 (Auto), Swing: Off, " - "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Breeze: Off, " - "Light: On, Ion: Off", + "Power: On, Mode: 1 (Cool), Temp: 24C, Fan: 0 (Auto), " + "Swing(V): Off, Swing(H): Off, " + "Beep: -, Clean: -, Quiet: Off, Powerful: Off, " + "Econo: Off, Breeze: Off, Light: On, Ion: Off", ac.toString()); } @@ -912,9 +990,10 @@ TEST(TestDecodeSamsungAC, DecodePowerOnSample) { IRSamsungAc ac(kGpioUnused); ac.setRaw(irsend.capture.state, kSamsungAcExtendedStateLength); EXPECT_EQ( - "Power: On, Mode: 1 (Cool), Temp: 24C, Fan: 0 (Auto), Swing: Off, " - "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Breeze: Off, " - "Light: On, Ion: Off", + "Power: On, Mode: 1 (Cool), Temp: 24C, Fan: 0 (Auto), " + "Swing(V): Off, Swing(H): Off, " + "Beep: -, Clean: -, Quiet: Off, Powerful: Off, " + "Econo: Off, Breeze: Off, Light: On, Ion: Off", ac.toString()); } @@ -973,9 +1052,10 @@ TEST(TestDecodeSamsungAC, DecodePowerOffSample) { IRSamsungAc ac(kGpioUnused); ac.setRaw(irsend.capture.state, kSamsungAcExtendedStateLength); EXPECT_EQ( - "Power: Off, Mode: 1 (Cool), Temp: 24C, Fan: 0 (Auto), Swing: Off, " - "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Breeze: Off, " - "Light: On, Ion: Off", + "Power: Off, Mode: 1 (Cool), Temp: 24C, Fan: 0 (Auto), " + "Swing(V): Off, Swing(H): Off, " + "Beep: -, Clean: -, Quiet: Off, Powerful: Off, " + "Econo: Off, Breeze: Off, Light: On, Ion: Off", ac.toString()); } @@ -1021,9 +1101,10 @@ TEST(TestDecodeSamsungAC, DecodeHeatSample) { IRSamsungAc ac(kGpioUnused); ac.setRaw(irsend.capture.state); EXPECT_EQ( - "Power: On, Mode: 4 (Heat), Temp: 17C, Fan: 0 (Auto), Swing: On, " - "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Breeze: Off, " - "Light: On, Ion: Off", + "Power: On, Mode: 4 (Heat), Temp: 17C, Fan: 0 (Auto), " + "Swing(V): On, Swing(H): Off, " + "Beep: -, Clean: -, Quiet: Off, Powerful: Off, " + "Econo: Off, Breeze: Off, Light: On, Ion: Off", ac.toString()); } @@ -1066,9 +1147,10 @@ TEST(TestDecodeSamsungAC, DecodeCoolSample) { EXPECT_EQ(kSamsungAcBits, irsend.capture.bits); EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); EXPECT_EQ( - "Power: On, Mode: 1 (Cool), Temp: 20C, Fan: 0 (Auto), Swing: Off, " - "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Breeze: Off, " - "Light: On, Ion: Off", + "Power: On, Mode: 1 (Cool), Temp: 20C, Fan: 0 (Auto), " + "Swing(V): Off, Swing(H): Off, " + "Beep: -, Clean: -, Quiet: Off, Powerful: Off, " + "Econo: Off, Breeze: Off, Light: On, Ion: Off", IRAcUtils::resultAcToString(&irsend.capture)); stdAc::state_t r, p; ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &r, &p)); @@ -1127,9 +1209,10 @@ TEST(TestDecodeSamsungAC, Issue604DecodeExtended) { IRSamsungAc ac(kGpioUnused); ac.setRaw(irsend.capture.state, irsend.capture.bits / 8); EXPECT_EQ( - "Power: Off, Mode: 4 (Heat), Temp: 30C, Fan: 0 (Auto), Swing: Off, " - "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Breeze: Off, " - "Light: On, Ion: Off", + "Power: Off, Mode: 4 (Heat), Temp: 30C, Fan: 0 (Auto), " + "Swing(V): On, Swing(H): On, " + "Beep: -, Clean: -, Quiet: Off, Powerful: Off, " + "Econo: Off, Breeze: Off, Light: On, Ion: Off", ac.toString()); } @@ -1311,8 +1394,10 @@ TEST(TestIRSamsungAcClass, Issue604SendPowerHack) { "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436" "m586s2886"; std::string text = "Power: On, Mode: 1 (Cool), Temp: 23C, Fan: 4 (Med), " - "Swing: On, Beep: Off, Clean: Off, Quiet: Off, " - "Powerful: Off, Breeze: Off, Light: On, Ion: Off"; + "Swing(V): On, Swing(H): Off, " + "Beep: -, Clean: -, Quiet: Off, " + "Powerful: Off, Econo: Off, Breeze: Off, " + "Light: On, Ion: Off"; // Don't do a setPower()/on()/off() as that will trigger the special message. // So it should only be the normal "settings" message. ac.setTemp(23); @@ -1445,9 +1530,10 @@ TEST(TestDecodeSamsungAC, Issue734QuietSetting) { IRSamsungAc ac(0); ac.setRaw(irsend.capture.state, irsend.capture.bits / 8); EXPECT_EQ( - "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 0 (Auto), Swing: Off, " - "Beep: Off, Clean: Off, Quiet: On, Powerful: Off, Breeze: Off, " - "Light: On, Ion: Off", + "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 0 (Auto), " + "Swing(V): Off, Swing(H): Off, " + "Beep: -, Clean: -, Quiet: On, Powerful: Off, " + "Econo: Off, Breeze: Off, Light: On, Ion: Off", ac.toString()); // Make sure the ac class state is in something wildly different first. @@ -1468,9 +1554,10 @@ TEST(TestDecodeSamsungAC, Issue734QuietSetting) { ac.setClean(false); ac.setQuiet(true); EXPECT_EQ( - "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 0 (Auto), Swing: Off, " - "Beep: Off, Clean: Off, Quiet: On, Powerful: Off, Breeze: Off, " - "Light: On, Ion: Off", + "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 0 (Auto), " + "Swing(V): Off, Swing(H): Off, " + "Beep: -, Clean: -, Quiet: On, Powerful: Off, " + "Econo: Off, Breeze: Off, Light: On, Ion: Off", ac.toString()); // Check it matches the known good/expected state. EXPECT_STATE_EQ(expectedState, ac.getRaw(), kSamsungAcBits); @@ -1519,9 +1606,10 @@ TEST(TestDecodeSamsungAC, Issue734PowerfulOff) { IRSamsungAc ac(0); ac.setRaw(irsend.capture.state, irsend.capture.bits / 8); EXPECT_EQ( - "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 0 (Auto), Swing: Off, " - "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Breeze: Off, " - "Light: On, Ion: Off", + "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 0 (Auto), " + "Swing(V): Off, Swing(H): Off, " + "Beep: -, Clean: -, Quiet: Off, Powerful: Off, " + "Econo: Off, Breeze: Off, Light: On, Ion: Off", ac.toString()); } @@ -1553,9 +1641,10 @@ TEST(TestIRSamsungAcClass, SetAndGetBreeze) { ac.setRaw(on); ASSERT_TRUE(ac.getBreeze()); EXPECT_EQ( - "Power: On, Mode: 3 (Fan), Temp: 24C, Fan: 0 (Auto), Swing: Off, " - "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Breeze: On, " - "Light: On, Ion: Off", + "Power: On, Mode: 3 (Fan), Temp: 24C, Fan: 0 (Auto), " + "Swing(V): Off, Swing(H): Off, " + "Beep: -, Clean: -, Quiet: Off, Powerful: Off, " + "Econo: Off, Breeze: On, Light: On, Ion: Off", ac.toString()); // MODE FAN, 24C WINDFREE OFF, FAN = LOW const uint8_t off[14] = { @@ -1564,9 +1653,10 @@ TEST(TestIRSamsungAcClass, SetAndGetBreeze) { ac.setRaw(off); ASSERT_FALSE(ac.getBreeze()); EXPECT_EQ( - "Power: On, Mode: 3 (Fan), Temp: 24C, Fan: 2 (Low), Swing: Off, " - "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Breeze: Off, " - "Light: On, Ion: Off", + "Power: On, Mode: 3 (Fan), Temp: 24C, Fan: 2 (Low), " + "Swing(V): Off, Swing(H): Off, " + "Beep: -, Clean: -, Quiet: Off, Powerful: Off, " + "Econo: Off, Breeze: Off, Light: On, Ion: Off", ac.toString()); } @@ -1614,9 +1704,10 @@ TEST(TestDecodeSamsungAC, Issue1227VeryPoorSignal) { EXPECT_EQ(kSamsungAcBits, irsend.capture.bits); EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); EXPECT_EQ( - "Power: On, Mode: 0 (Auto), Temp: 17C, Fan: 0 (Auto), Swing: Off, " - "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Breeze: Off, " - "Light: Off, Ion: Off", + "Power: On, Mode: 0 (Auto), Temp: 17C, Fan: 0 (Auto), " + "Swing(V): Off, Swing(H): Off, " + "Beep: -, Clean: -, Quiet: Off, Powerful: Off, " + "Econo: Off, Breeze: Off, Light: Off, Ion: Off", IRAcUtils::resultAcToString(&irsend.capture)); stdAc::state_t r, p; ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &r, &p)); @@ -1671,3 +1762,362 @@ TEST(TestIRSamsungAcClass, SectionChecksums) { EXPECT_EQ(IRSamsungAc::getSectionChecksum(extended_off + 14), IRSamsungAc::calcSectionChecksum(extended_off + 14)); } + +TEST(TestIRSamsungAcClass, Issue1648) { + IRSamsungAc ac(kGpioUnused); + IRrecv irrecv(kGpioUnused); + const uint8_t onState[kSamsungAcExtendedStateLength] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, + 0x01, 0xD2, 0x0F, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xC2, 0xFE, 0x71, 0x90, 0x15, 0xF0}; + const String onText = "Power: On, Mode: 1 (Cool), Temp: 25C, Fan: 2 (Low), " + "Swing(V): Off, Swing(H): Off, " + "Beep: -, Clean: -, Quiet: Off, " + "Powerful: Off, Econo: Off, Breeze: Off, " + "Light: On, Ion: Off"; + const uint8_t extended_offState[kSamsungAcExtendedStateLength] = { + 0x02, 0xB2, 0x0F, 0x00, 0x00, 0x00, 0xC0, + 0x01, 0xD2, 0x0F, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xE2, 0xFE, 0x71, 0x90, 0x15, 0xC0}; + const uint8_t short_offState[kSamsungAcStateLength] = { + 0x02, 0xB2, 0x0F, 0x00, 0x00, 0x00, 0xC0, + 0x01, 0xE2, 0xFE, 0x71, 0x90, 0x15, 0xC0}; + const String offText = "Power: Off, Mode: 1 (Cool), Temp: 25C, Fan: 2 (Low), " + "Swing(V): Off, Swing(H): Off, " + "Beep: -, Clean: -, Quiet: Off, " + "Powerful: Off, Econo: Off, Breeze: Off, " + "Light: On, Ion: Off"; + const uint8_t coolState[kSamsungAcStateLength] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, + 0x01, 0xC2, 0xFE, 0x71, 0x90, 0x15, 0xF0}; + + // "setup()"" from provided code. + ac.begin(); // User code + ac.off(); // User code + ac.setFan(kSamsungAcFanLow); // User code + ac.setMode(kSamsungAcCool); // User code + ac.setTemp(25); // User code + ac.setSwing(false); // User code + + // Go through "loop()" from provided code. + for (uint8_t i = 0; i < 2; i++) { + ac.on(); // User code + ac.send(); // User code + + // Verify what was sent. + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&ac._irsend.capture)); + EXPECT_EQ(SAMSUNG_AC, ac._irsend.capture.decode_type); + EXPECT_EQ(kSamsungAcExtendedBits, ac._irsend.capture.bits); + EXPECT_STATE_EQ(onState, ac._irsend.capture.state, ac._irsend.capture.bits); + EXPECT_EQ(onText, IRAcUtils::resultAcToString(&ac._irsend.capture)); + EXPECT_TRUE(ac._lastsentpowerstate); + ac._irsend.reset(); + + ac.setMode(kSamsungAcCool); // User code + ac.send(); // User code + + // Verify what was sent. + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&ac._irsend.capture)); + EXPECT_EQ(SAMSUNG_AC, ac._irsend.capture.decode_type); + EXPECT_EQ(kSamsungAcBits, ac._irsend.capture.bits); + EXPECT_STATE_EQ(coolState, ac._irsend.capture.state, + ac._irsend.capture.bits); + EXPECT_EQ(onText, IRAcUtils::resultAcToString(&ac._irsend.capture)); + ac._irsend.reset(); + EXPECT_TRUE(ac._lastsentpowerstate); + EXPECT_FALSE(ac._forceextended); + + ac.off(); // User code + ac.send(); // User code + + // Verify what was sent. + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&ac._irsend.capture)); + EXPECT_EQ(SAMSUNG_AC, ac._irsend.capture.decode_type); + EXPECT_EQ(kSamsungAcExtendedBits, ac._irsend.capture.bits); + EXPECT_STATE_EQ(extended_offState, ac._irsend.capture.state, + ac._irsend.capture.bits); + EXPECT_EQ(offText, IRAcUtils::resultAcToString(&ac._irsend.capture)); + EXPECT_FALSE(ac._lastsentpowerstate); + ac._irsend.reset(); + + ac.off(); // User code + ac.send(); // User code + + // Verify what was sent. + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&ac._irsend.capture)); + EXPECT_EQ(SAMSUNG_AC, ac._irsend.capture.decode_type); + EXPECT_EQ(kSamsungAcBits, ac._irsend.capture.bits); + EXPECT_STATE_EQ(short_offState, ac._irsend.capture.state, + ac._irsend.capture.bits); + EXPECT_EQ(offText, IRAcUtils::resultAcToString(&ac._irsend.capture)); + EXPECT_FALSE(ac._lastsentpowerstate); + ac._irsend.reset(); + // End of "loop()" code. + } + + // Data from https://github.com/crankyoldgit/IRremoteESP8266/issues/1648#issuecomment-950822399 + const uint8_t expectedState[kSamsungAcExtendedStateLength] = { + 0x02, 0xB2, 0x0F, 0x00, 0x00, 0x00, 0xC0, + 0x01, 0xD2, 0x0F, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x12, 0xAF, 0x71, 0x80, 0x15, 0xC0}; + const String expectedText = "Power: Off, Mode: 1 (Cool), Temp: 24C, " + "Fan: 2 (Low), Swing(V): On, Swing(H): Off, " + "Beep: -, Clean: -, " + "Quiet: Off, Powerful: Off, Econo: Off, " + "Breeze: Off, Light: On, Ion: Off"; + + ac.stateReset(); + ac.setRaw(expectedState, kSamsungAcExtendedStateLength); + EXPECT_EQ(expectedText, ac.toString()); + + // Try to generate the same message. + ac.stateReset(); + ac.off(); + ac.setMode(kSamsungAcCool); + ac.setTemp(24); + ac.setFan(kSamsungAcFanLow); + ac.setSwing(true); + ac.setBeep(false); + ac.setClean(false); + ac.setQuiet(false); + ac.setPowerful(false); + ac.setBreeze(false); + ac.setDisplay(true); + ac.setIon(false); + EXPECT_EQ(expectedText, ac.toString()); + + ac.send(); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&ac._irsend.capture)); + EXPECT_EQ(SAMSUNG_AC, ac._irsend.capture.decode_type); + EXPECT_EQ(kSamsungAcExtendedBits, ac._irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, ac._irsend.capture.state, + ac._irsend.capture.bits); + EXPECT_EQ(expectedText, IRAcUtils::resultAcToString(&ac._irsend.capture)); + ac._irsend.reset(); +} + +TEST(TestIRSamsungAcClass, Timers) { + IRSamsungAc ac(kGpioUnused); + ac.begin(); + + // https://github.com/crankyoldgit/IRremoteESP8266/issues/1277#issuecomment-961836703 + const uint8_t on_timer_30m[kSamsungAcExtendedStateLength] = { + 0x02, 0xB2, 0x0F, 0x00, 0x00, 0x00, 0xC0, + 0x01, 0xA2, 0x0F, 0x30, 0x00, 0x02, 0x00, + 0x01, 0x02, 0xFF, 0x71, 0x40, 0x11, 0xC0}; + const uint8_t off_timer_1h_on_timer_10m[kSamsungAcExtendedStateLength] = { + 0x02, 0xB2, 0x0F, 0x00, 0x00, 0x00, 0xC0, + 0x01, 0x92, 0x8F, 0x10, 0x00, 0x06, 0x00, + 0x01, 0x02, 0xFF, 0x71, 0x40, 0x11, 0xC0}; + const uint8_t off_timer_1h_on_timer_0m[kSamsungAcExtendedStateLength] = { + 0x02, 0xB2, 0x0F, 0x00, 0x00, 0x00, 0xC0, + 0x01, 0xA2, 0x8F, 0x00, 0x00, 0x06, 0x00, + 0x01, 0x02, 0xFF, 0x71, 0x40, 0x11, 0xC0}; + + ac.setRaw(on_timer_30m, kSamsungAcExtendedStateLength); + EXPECT_EQ( + "Power: Off, Mode: 1 (Cool), Temp: 20C, Fan: 0 (Auto), " + "Swing(V): Off, Swing(H): Off, " + "Beep: -, Clean: -, Quiet: Off, Powerful: Off, " + "Econo: Off, Breeze: Off, Light: On, Ion: Off, On Timer: 00:30", + ac.toString()); + ac.setRaw(off_timer_1h_on_timer_10m, kSamsungAcExtendedStateLength); + EXPECT_EQ( + "Power: Off, Mode: 1 (Cool), Temp: 20C, Fan: 0 (Auto), " + "Swing(V): Off, Swing(H): Off, " + "Beep: -, Clean: -, Quiet: Off, Powerful: Off, " + "Econo: Off, Breeze: Off, " + "Light: On, Ion: Off, On Timer: 00:10, Off Timer: 01:00", + ac.toString()); + ac.setRaw(off_timer_1h_on_timer_0m, kSamsungAcExtendedStateLength); + EXPECT_EQ( + "Power: Off, Mode: 1 (Cool), Temp: 20C, Fan: 0 (Auto), " + "Swing(V): Off, Swing(H): Off, " + "Beep: -, Clean: -, Quiet: Off, Powerful: Off, " + "Econo: Off, Breeze: Off, " + "Light: On, Ion: Off, On Timer: 00:00, Off Timer: 01:00", + ac.toString()); + + // https://cryptpad.fr/sheet/#/2/sheet/view/r9k8pmELYEjLyC71cD7EsThEYgKGLJygREZ5pVfNkS8/ + // Row 155 + const uint8_t off_timer_11h_on_timer_6h[kSamsungAcExtendedStateLength] = { + 0x02, 0xB2, 0x0F, 0x00, 0x00, 0x00, 0xC0, + 0x01, 0x62, 0x8F, 0x05, 0x03, 0x06, 0x00, + 0x01, 0x02, 0xFF, 0x71, 0x40, 0x11, 0xC0}; + ac.setRaw(off_timer_11h_on_timer_6h, kSamsungAcExtendedStateLength); + EXPECT_EQ( + "Power: Off, Mode: 1 (Cool), Temp: 20C, Fan: 0 (Auto), " + "Swing(V): Off, Swing(H): Off, " + "Beep: -, Clean: -, Quiet: Off, Powerful: Off, " + "Econo: Off, Breeze: Off, " + "Light: On, Ion: Off, On Timer: 06:00, Off Timer: 11:00", + ac.toString()); + + ac.stateReset(false); + EXPECT_EQ(0, ac.getOnTimer()); + EXPECT_EQ(0, ac.getOffTimer()); + + ac.setOnTimer(0); + EXPECT_EQ(0, ac.getOnTimer()); + EXPECT_EQ(0, ac.getOffTimer()); + + ac.setOffTimer(0); + EXPECT_EQ(0, ac.getOnTimer()); + EXPECT_EQ(0, ac.getOffTimer()); + + // On Timer only + ac.setOnTimer(30); + EXPECT_EQ(30, ac.getOnTimer()); + EXPECT_EQ(0, ac.getOffTimer()); + + ac.setOnTimer(90); // 1h30m + EXPECT_EQ(90, ac.getOnTimer()); + EXPECT_EQ(0, ac.getOffTimer()); + + ac.setOnTimer(85); // 1h25m -> 1h20m + EXPECT_EQ(80, ac.getOnTimer()); + EXPECT_EQ(0, ac.getOffTimer()); + + ac.setOnTimer(23 * 60 + 59); // 23:59 + EXPECT_EQ(23 * 60 + 50, ac.getOnTimer()); // 23:50 + EXPECT_EQ(0, ac.getOffTimer()); + + ac.setOnTimer(24 * 60 + 30); // 24:30 + EXPECT_EQ(24 * 60, ac.getOnTimer()); // 24:00 (Max) + EXPECT_EQ(0, ac.getOffTimer()); + + // Off Timer only + ac.setOnTimer(0); + ac.setOffTimer(0); + EXPECT_EQ(0, ac.getOnTimer()); + EXPECT_EQ(0, ac.getOffTimer()); + + ac.setOffTimer(30); + EXPECT_EQ(30, ac.getOffTimer()); + EXPECT_EQ(0, ac.getOnTimer()); + + ac.setOffTimer(90); // 1h30m + EXPECT_EQ(90, ac.getOffTimer()); + EXPECT_EQ(0, ac.getOnTimer()); + + ac.setOffTimer(85); // 1h25m -> 1h20m + EXPECT_EQ(80, ac.getOffTimer()); + EXPECT_EQ(0, ac.getOnTimer()); + + ac.setOffTimer(23 * 60 + 59); // 23:59 + EXPECT_EQ(23 * 60 + 50, ac.getOffTimer()); // 23:50 + EXPECT_EQ(0, ac.getOnTimer()); + + ac.setOffTimer(24 * 60 + 30); // 24:30 + EXPECT_EQ(24 * 60, ac.getOffTimer()); // 24:00 (Max) + EXPECT_EQ(0, ac.getOnTimer()); + + // Both Timers + ac.setOnTimer(24 * 60); // 24:00 + EXPECT_EQ(24 * 60, ac.getOnTimer()); // 24:00 (Max) + EXPECT_EQ(24 * 60, ac.getOffTimer()); // 24:00 (Max) + + ac.setOnTimer(1 * 60 + 30); // 1:30 + ac.setOffTimer(11 * 60); // 11:00 + EXPECT_EQ(1 * 60 + 30, ac.getOnTimer()); + EXPECT_EQ(11 * 60, ac.getOffTimer()); +} + +TEST(TestIRSamsungAcClass, Sleep) { + IRSamsungAc ac(kGpioUnused); + ac.begin(); + + // https://cryptpad.fr/sheet/#/2/sheet/view/r9k8pmELYEjLyC71cD7EsThEYgKGLJygREZ5pVfNkS8/ + const uint8_t sleep_8h[kSamsungAcExtendedStateLength] = { + 0x02, 0x82, 0x0F, 0x00, 0x00, 0x10, 0xF0, + 0x01, 0xA2, 0x0F, 0x04, 0x00, 0x0C, 0x00, + 0x01, 0xE2, 0xFE, 0x71, 0x40, 0x11, 0xF0}; + ac.setRaw(sleep_8h, kSamsungAcExtendedStateLength); + EXPECT_EQ(8 * 60, ac.getSleepTimer()); + EXPECT_EQ(0, ac.getOffTimer()); + EXPECT_EQ(0, ac.getOnTimer()); + EXPECT_EQ( + "Power: On, Mode: 1 (Cool), Temp: 20C, Fan: 0 (Auto), " + "Swing(V): Off, Swing(H): Off, " + "Beep: -, Clean: -, Quiet: Off, Powerful: Off, " + "Econo: Off, Breeze: Off, " + "Light: On, Ion: Off, Sleep Timer: 08:00", + ac.toString()); + + ac.stateReset(false); + EXPECT_EQ(0, ac.getSleepTimer()); + EXPECT_EQ(0, ac.getOnTimer()); + EXPECT_EQ(0, ac.getOffTimer()); + + ac.setOnTimer(60); + ac.setOffTimer(90); + EXPECT_EQ(0, ac.getSleepTimer()); + EXPECT_EQ(60, ac.getOnTimer()); + EXPECT_EQ(90, ac.getOffTimer()); + + ac.setSleepTimer(120); + EXPECT_EQ(120, ac.getSleepTimer()); + EXPECT_EQ(0, ac.getOnTimer()); + EXPECT_EQ(0, ac.getOffTimer()); + + ac.setSleepTimer(24 * 60 + 31); // 24h31m + EXPECT_EQ(24 * 60, ac.getSleepTimer()); // 24h (Max) + + ac.setSleepTimer(35); // 45m + EXPECT_EQ(30, ac.getSleepTimer()); // 30m (Only stored in 10m increments). + + ac.setOnTimer(60); // Seting an On Timer should clear the sleep setting. + EXPECT_EQ(0, ac.getSleepTimer()); + EXPECT_EQ(60, ac.getOnTimer()); + + ac.setSleepTimer(120); + ac.setOffTimer(90); // Setting an Off Timer will clear the sleep setting. + EXPECT_EQ(0, ac.getSleepTimer()); + EXPECT_EQ(0, ac.getOnTimer()); + EXPECT_EQ(90, ac.getOffTimer()); +} + +TEST(TestIRSamsungAcClass, BuildKnownSleepSate) { + // For https://github.com/crankyoldgit/IRremoteESP8266/issues/1277#issuecomment-965047193 + IRSamsungAc ac(kGpioUnused); + IRrecv irrecv(kGpioUnused); + ac.begin(); + const uint8_t expectedState[kSamsungAcExtendedStateLength] = { + 0x02, 0x82, 0x0F, 0x00, 0x00, 0x10, 0xF0, + 0x01, 0xA2, 0x0F, 0x04, 0x00, 0x0C, 0x00, + 0x01, 0xD2, 0xFE, 0x71, 0x50, 0x41, 0xF0}; + const char expectedStr[] = "Power: On, Mode: 4 (Heat), Temp: 21C, " + "Fan: 0 (Auto), Swing(V): Off, Swing(H): Off, Beep: -, Clean: -, " + "Quiet: Off, Powerful: Off, Econo: Off, Breeze: Off, " + "Light: On, Ion: Off, Sleep Timer: 08:00"; + ac.setPower(true); + ac.setMode(kSamsungAcHeat); + ac.setTemp(21); + ac.setFan(kSamsungAcFanAuto); + ac.setSwing(false); + ac.setSwingH(false); + ac.setBeep(false); + ac.setClean(false); + ac.setQuiet(false); + ac.setPowerful(false); + ac.setEcono(false); + ac.setBreeze(false); + ac.setDisplay(true); + ac.setIon(false); + ac.setSleepTimer(8 * 60); + EXPECT_EQ(expectedStr, ac.toString()); + ac.send(); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&ac._irsend.capture)); + EXPECT_EQ(SAMSUNG_AC, ac._irsend.capture.decode_type); + EXPECT_EQ(kSamsungAcExtendedBits, ac._irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, ac._irsend.capture.state, + ac._irsend.capture.bits); + EXPECT_EQ(expectedStr, IRAcUtils::resultAcToString(&ac._irsend.capture)); + ac._irsend.reset(); +} diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Sharp_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Sharp_test.cpp index bf08c644a..a2acafb9c 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Sharp_test.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Sharp_test.cpp @@ -410,8 +410,8 @@ TEST(TestDecodeSharpAc, RealExample) { EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); EXPECT_EQ( "Model: 1 (A907), " - "Power: On, Mode: 2 (Cool), Temp: 27C, Fan: 2 (Auto), Turbo: Off, " - "Swing(V) Toggle: Off, Ion: Off, Econo: -, Clean: Off", + "Power: On, Mode: 2 (Cool), Temp: 27C, Fan: 2 (Auto), " + "Swing(V): 0 (N/A), Turbo: Off, Ion: Off, Econo: -, Clean: Off", IRAcUtils::resultAcToString(&irsend.capture)); stdAc::state_t r, p; ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &r, &p)); @@ -561,7 +561,7 @@ TEST(TestSharpAcClass, OperatingMode) { // Check toString() says Fan rather than Auto. EXPECT_EQ( "Model: 2 (A705), Power: Off, Mode: 0 (Fan), Temp: 15C, Fan: 2 (Auto), " - "Turbo: Off, Swing(V) Toggle: Off, Ion: Off, Light: -, Clean: Off", + "Swing(V): 0 (N/A), Turbo: Off, Ion: Off, Light: -, Clean: Off", ac.toString()); } @@ -615,8 +615,8 @@ TEST(TestSharpAcClass, ReconstructKnownState) { EXPECT_STATE_EQ(on_auto_auto, ac.getRaw(), kSharpAcBits); EXPECT_EQ( "Model: 1 (A907), " - "Power: On, Mode: 0 (Auto), Temp: 15C, Fan: 2 (Auto), Turbo: Off, " - "Swing(V) Toggle: Off, Ion: Off, Econo: -, Clean: Off", + "Power: On, Mode: 0 (Auto), Temp: 15C, Fan: 2 (Auto), Swing(V): 0 (N/A), " + "Turbo: Off, Ion: Off, Econo: -, Clean: Off", ac.toString()); uint8_t cool_auto_28[kSharpAcStateLength] = { @@ -629,8 +629,8 @@ TEST(TestSharpAcClass, ReconstructKnownState) { ac.setTemp(28); EXPECT_EQ( "Model: 1 (A907), " - "Power: On, Mode: 2 (Cool), Temp: 28C, Fan: 2 (Auto), Turbo: Off, " - "Swing(V) Toggle: Off, Ion: Off, Econo: -, Clean: Off", + "Power: On, Mode: 2 (Cool), Temp: 28C, Fan: 2 (Auto), Swing(V): 0 (N/A), " + "Turbo: Off, Ion: Off, Econo: -, Clean: Off", ac.toString()); EXPECT_STATE_EQ(cool_auto_28, ac.getRaw(), kSharpAcBits); } @@ -647,8 +647,8 @@ TEST(TestSharpAcClass, KnownStates) { ac.setRaw(off_auto_auto); EXPECT_EQ( "Model: 1 (A907), " - "Power: Off, Mode: 0 (Auto), Temp: 15C, Fan: 2 (Auto), Turbo: Off, " - "Swing(V) Toggle: Off, Ion: Off, Econo: -, Clean: Off", + "Power: Off, Mode: 0 (Auto), Temp: 15C, Fan: 2 (Auto), " + "Swing(V): 0 (N/A), Turbo: Off, Ion: Off, Econo: -, Clean: Off", ac.toString()); uint8_t on_auto_auto[kSharpAcStateLength] = { 0xAA, 0x5A, 0xCF, 0x10, 0x00, 0x11, 0x20, 0x00, 0x08, 0x80, 0x00, 0xE0, @@ -657,8 +657,8 @@ TEST(TestSharpAcClass, KnownStates) { ac.setRaw(on_auto_auto); EXPECT_EQ( "Model: 1 (A907), " - "Power: On, Mode: 0 (Auto), Temp: 15C, Fan: 2 (Auto), Turbo: Off, " - "Swing(V) Toggle: Off, Ion: Off, Econo: -, Clean: Off", + "Power: On, Mode: 0 (Auto), Temp: 15C, Fan: 2 (Auto), Swing(V): 0 (N/A), " + "Turbo: Off, Ion: Off, Econo: -, Clean: Off", ac.toString()); uint8_t cool_auto_28[kSharpAcStateLength] = { 0xAA, 0x5A, 0xCF, 0x10, 0xCD, 0x31, 0x22, 0x00, 0x08, 0x80, 0x04, 0xE0, @@ -667,8 +667,8 @@ TEST(TestSharpAcClass, KnownStates) { ac.setRaw(cool_auto_28); EXPECT_EQ( "Model: 1 (A907), " - "Power: On, Mode: 2 (Cool), Temp: 28C, Fan: 2 (Auto), Turbo: Off, " - "Swing(V) Toggle: Off, Ion: Off, Econo: -, Clean: Off", + "Power: On, Mode: 2 (Cool), Temp: 28C, Fan: 2 (Auto), Swing(V): 0 (N/A), " + "Turbo: Off, Ion: Off, Econo: -, Clean: Off", ac.toString()); uint8_t cool_fan1_28[kSharpAcStateLength] = { 0xAA, 0x5A, 0xCF, 0x10, 0xCD, 0x31, 0x42, 0x00, 0x08, 0x80, 0x05, 0xE0, @@ -677,8 +677,8 @@ TEST(TestSharpAcClass, KnownStates) { ac.setRaw(cool_fan1_28); EXPECT_EQ( "Model: 1 (A907), " - "Power: On, Mode: 2 (Cool), Temp: 28C, Fan: 4 (Low), Turbo: Off, " - "Swing(V) Toggle: Off, Ion: Off, Econo: -, Clean: Off", + "Power: On, Mode: 2 (Cool), Temp: 28C, Fan: 4 (Low), Swing(V): 0 (N/A), " + "Turbo: Off, Ion: Off, Econo: -, Clean: Off", ac.toString()); uint8_t cool_fan2_28[kSharpAcStateLength] = { 0xAA, 0x5A, 0xCF, 0x10, 0xCD, 0x31, 0x32, 0x00, 0x08, 0x80, 0x05, 0xE0, @@ -688,7 +688,7 @@ TEST(TestSharpAcClass, KnownStates) { EXPECT_EQ( "Model: 1 (A907), " "Power: On, Mode: 2 (Cool), Temp: 28C, Fan: 3 (Medium), " - "Turbo: Off, Swing(V) Toggle: Off, Ion: Off, Econo: -, Clean: Off", + "Swing(V): 0 (N/A), Turbo: Off, Ion: Off, Econo: -, Clean: Off", ac.toString()); uint8_t cool_fan3_28[kSharpAcStateLength] = { 0xAA, 0x5A, 0xCF, 0x10, 0xCD, 0x31, 0x52, 0x00, 0x08, 0x80, 0x05, 0xE0, @@ -698,7 +698,7 @@ TEST(TestSharpAcClass, KnownStates) { EXPECT_EQ( "Model: 1 (A907), " "Power: On, Mode: 2 (Cool), Temp: 28C, Fan: 5 (UNKNOWN), " - "Turbo: Off, Swing(V) Toggle: Off, Ion: Off, Econo: -, Clean: Off", + "Swing(V): 0 (N/A), Turbo: Off, Ion: Off, Econo: -, Clean: Off", ac.toString()); uint8_t cool_fan4_28[kSharpAcStateLength] = { 0xAA, 0x5A, 0xCF, 0x10, 0xCD, 0x31, 0x72, 0x00, 0x08, 0x80, 0x05, 0xE0, @@ -707,8 +707,8 @@ TEST(TestSharpAcClass, KnownStates) { ac.setRaw(cool_fan4_28); EXPECT_EQ( "Model: 1 (A907), " - "Power: On, Mode: 2 (Cool), Temp: 28C, Fan: 7 (High), Turbo: Off, " - "Swing(V) Toggle: Off, Ion: Off, Econo: -, Clean: Off", + "Power: On, Mode: 2 (Cool), Temp: 28C, Fan: 7 (High), Swing(V): 0 (N/A), " + "Turbo: Off, Ion: Off, Econo: -, Clean: Off", ac.toString()); uint8_t cool_fan4_28_ion_on[kSharpAcStateLength] = { 0xAA, 0x5A, 0xCF, 0x10, 0xCD, 0x61, 0x72, 0x08, 0x08, 0x80, 0x00, 0xE4, @@ -717,8 +717,8 @@ TEST(TestSharpAcClass, KnownStates) { ac.setRaw(cool_fan4_28_ion_on); EXPECT_EQ( "Model: 1 (A907), " - "Power: -, Mode: 2 (Cool), Temp: 28C, Fan: 7 (High), Turbo: Off, " - "Swing(V) Toggle: Off, Ion: On, Econo: -, Clean: Off", + "Power: -, Mode: 2 (Cool), Temp: 28C, Fan: 7 (High), Swing(V): 0 (N/A), " + "Turbo: Off, Ion: On, Econo: -, Clean: Off", ac.toString()); /* Unsupported / Not yet reverse engineered. uint8_t cool_fan4_28_eco1[kSharpAcStateLength] = { @@ -735,8 +735,8 @@ TEST(TestSharpAcClass, KnownStates) { ac.setRaw(dry_auto); EXPECT_EQ( "Model: 1 (A907), " - "Power: On, Mode: 3 (Dry), Temp: 15C, Fan: 2 (Auto), Turbo: Off, " - "Swing(V) Toggle: Off, Ion: Off, Econo: -, Clean: Off", + "Power: On, Mode: 3 (Dry), Temp: 15C, Fan: 2 (Auto), Swing(V): 0 (N/A), " + "Turbo: Off, Ion: Off, Econo: -, Clean: Off", ac.toString()); } @@ -747,6 +747,7 @@ TEST(TestSharpAcClass, toCommon) { ac.setMode(kSharpAcCool); ac.setTemp(20); ac.setFan(kSharpAcFanMax); + ac.setSwingV(kSharpAcSwingVOff); // Now test it. ASSERT_EQ(decode_type_t::SHARP_AC, ac.toCommon().protocol); ASSERT_TRUE(ac.toCommon().power); @@ -755,8 +756,8 @@ TEST(TestSharpAcClass, toCommon) { ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode); ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed); ASSERT_EQ(sharp_ac_remote_model_t::A705, ac.toCommon().model); - // Unsupported. ASSERT_EQ(stdAc::swingv_t::kOff, ac.toCommon().swingv); + // Unsupported. ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh); ASSERT_FALSE(ac.toCommon().turbo); ASSERT_FALSE(ac.toCommon().quiet); @@ -868,20 +869,20 @@ TEST(TestSharpAcClass, Turbo) { EXPECT_EQ(kSharpAcFanMax, ac.getFan()); EXPECT_EQ( "Model: 3 (A903), " - "Power: -, Mode: 2 (Cool), Temp: 21C, Fan: 7 (High), Turbo: On, " - "Swing(V) Toggle: Off, Ion: On, Light: -, Clean: Off", + "Power: -, Mode: 2 (Cool), Temp: 21C, Fan: 7 (High), " + "Swing(V): 0 (N/A), Turbo: On, Ion: On, Light: -, Clean: Off", ac.toString()); ac.setRaw(off_state); EXPECT_FALSE(ac.getTurbo()); EXPECT_EQ( "Model: 3 (A903), " - "Power: -, Mode: 2 (Cool), Temp: 21C, Fan: 7 (High), Turbo: Off, " - "Swing(V) Toggle: Off, Ion: On, Light: -, Clean: Off", + "Power: -, Mode: 2 (Cool), Temp: 21C, Fan: 7 (High), " + "Swing(V): 0 (N/A), Turbo: Off, Ion: On, Light: -, Clean: Off", ac.toString()); } -TEST(TestSharpAcClass, SwingToggle) { +TEST(TestSharpAcClass, Swings) { IRSharpAc ac(kGpioUnused); ac.begin(); @@ -906,6 +907,70 @@ TEST(TestSharpAcClass, SwingToggle) { ac.setRaw(off_state); EXPECT_FALSE(ac.getSwingToggle()); + + // Vertical + ac.setSwingV(kSharpAcSwingVToggle); + EXPECT_EQ(kSharpAcSwingVToggle, ac.getSwingV()); + EXPECT_TRUE(ac.getSwingToggle()); + + ac.setSwingV(kSharpAcSwingVHigh); + EXPECT_EQ(kSharpAcSwingVHigh, ac.getSwingV()); + EXPECT_FALSE(ac.getSwingToggle()); + + ac.setSwingV(0xFF); // Doesn't change if invalid position given. + EXPECT_EQ(kSharpAcSwingVHigh, ac.getSwingV()); + + ac.setSwingV(kSharpAcSwingVMid); + EXPECT_EQ(kSharpAcSwingVMid, ac.getSwingV()); + EXPECT_FALSE(ac.getSwingToggle()); + + ac.setSwingV(kSharpAcSwingVLow); + EXPECT_EQ(kSharpAcSwingVLow, ac.getSwingV()); + EXPECT_FALSE(ac.getSwingToggle()); + + ac.setSwingV(kSharpAcSwingVIgnore); + EXPECT_EQ(kSharpAcSwingVIgnore, ac.getSwingV()); + EXPECT_FALSE(ac.getSwingToggle()); + + // Lowest/Coanda only works in Heat mode. + ac.setMode(kSharpAcCool); + ac.setSwingV(kSharpAcSwingVLowest); + EXPECT_EQ(kSharpAcSwingVLow, ac.getSwingV()); + EXPECT_FALSE(ac.getSwingToggle()); + ac.setModel(sharp_ac_remote_model_t::A907); // Model A907 has heat mode. + ac.setMode(kSharpAcHeat); + EXPECT_EQ(kSharpAcHeat, ac.getMode()); + ac.setSwingV(kSharpAcSwingVLowest); + EXPECT_EQ(kSharpAcSwingVLowest, ac.getSwingV()); + + // Check we can force Coanda in Cool mode. + ac.setMode(kSharpAcCool); + ASSERT_EQ(kSharpAcSwingVCoanda, kSharpAcSwingVLowest); + ac.setSwingV(kSharpAcSwingVCoanda, true); + EXPECT_EQ(kSharpAcSwingVCoanda, ac.getSwingV()); + EXPECT_FALSE(ac.getSwingToggle()); + EXPECT_EQ(kSharpAcCool, ac.getMode()); + + // Real messages/states + // ref: https://github.com/crankyoldgit/IRremoteESP8266/discussions/1590#discussioncomment-1254748 + ac.stateReset(); + const uint8_t coanda_heat_on[13] = { + 0xAA, 0x5A, 0xCF, 0x10, 0xC8, 0x31, 0x21, + 0x0A, 0x0E, 0x80, 0x06, 0xF4, 0x81}; + ac.setRaw(coanda_heat_on); + EXPECT_EQ( + "Model: 3 (A903), Power: On, Mode: 1 (Heat), Temp: 23C, Fan: 2 (Auto), " + "Swing(V): 6 (Lowest), Turbo: Off, Ion: On, Light: -, Clean: Off", + ac.toString()); + + const uint8_t coanda_cool_on[13] = { + 0xAA, 0x5A, 0xCF, 0x10, 0xC7, 0x31, 0x22, + 0x0A, 0x0E, 0x80, 0x06, 0xF4, 0x41}; + ac.setRaw(coanda_cool_on); + EXPECT_EQ( + "Model: 3 (A903), Power: On, Mode: 2 (Cool), Temp: 22C, Fan: 2 (Auto), " + "Swing(V): 6 (Highest), Turbo: Off, Ion: On, Light: -, Clean: Off", + ac.toString()); } TEST(TestSharpAcClass, Ion) { @@ -1005,8 +1070,8 @@ TEST(TestSharpAcClass, Timers) { EXPECT_TRUE(ac.isPowerSpecial()); EXPECT_EQ( "Model: 3 (A903), " - "Power: -, Mode: 2 (Cool), Temp: 21C, Fan: 7 (High), Turbo: Off, " - "Swing(V) Toggle: Off, Ion: On, Light: -, Clean: Off, Off Timer: 08:30", + "Power: -, Mode: 2 (Cool), Temp: 21C, Fan: 7 (High), Swing(V): 0 (N/A), " + "Turbo: Off, Ion: On, Light: -, Clean: Off, Off Timer: 08:30", ac.toString()); // ref: https://docs.google.com/spreadsheets/d/1otzVFM5_tegrZ4ROCLgQ_jvJaWCDlZs1vC-YuR1FFXM/edit#gid=0&range=E80 @@ -1020,7 +1085,7 @@ TEST(TestSharpAcClass, Timers) { EXPECT_TRUE(ac.isPowerSpecial()); EXPECT_EQ( "Model: 3 (A903), Power: -, Mode: 2 (Cool), Temp: 21C, Fan: 7 (High), " - "Turbo: Off, Swing(V) Toggle: Off, Ion: On, Light: -, Clean: Off, " + "Swing(V): 0 (N/A), Turbo: Off, Ion: On, Light: -, Clean: Off, " "On Timer: 12:00", ac.toString()); } @@ -1058,13 +1123,13 @@ TEST(TestSharpAcClass, Clean) { EXPECT_TRUE(ac.getClean()); EXPECT_EQ( "Model: 3 (A903), Power: On, Mode: 3 (Dry), Temp: 15C, Fan: 2 (Auto), " - "Turbo: Off, Swing(V) Toggle: Off, Ion: Off, Light: -, Clean: On", + "Swing(V): 0 (N/A), Turbo: Off, Ion: Off, Light: -, Clean: On", ac.toString()); ac.setRaw(clean_off_state); EXPECT_FALSE(ac.getClean()); EXPECT_EQ( "Model: 3 (A903), Power: On, Mode: 2 (Cool), Temp: 25C, Fan: 7 (High), " - "Turbo: Off, Swing(V) Toggle: Off, Ion: Off, Light: -, Clean: Off", + "Swing(V): 0 (N/A), Turbo: Off, Ion: Off, Light: -, Clean: Off", ac.toString()); // Try constructing the clean on state. @@ -1084,13 +1149,13 @@ TEST(TestSharpAcClass, Clean) { ac.setPower(false); EXPECT_EQ( "Model: 1 (A907), Power: Off, Mode: 2 (Cool), Temp: 25C, Fan: 7 (High), " - "Turbo: Off, Swing(V) Toggle: Off, Ion: Off, Econo: -, Clean: Off", + "Swing(V): 0 (N/A), Turbo: Off, Ion: Off, Econo: -, Clean: Off", ac.toString()); // Clean ON ac.setClean(true); EXPECT_EQ( "Model: 1 (A907), Power: On, Mode: 3 (Dry), Temp: 15C, Fan: 2 (Auto), " - "Turbo: Off, Swing(V) Toggle: Off, Ion: Off, Econo: -, Clean: On", + "Swing(V): 0 (N/A), Turbo: Off, Ion: Off, Econo: -, Clean: On", ac.toString()); // Clean OFF (state is identical to `off_msg`). // i.e. It just clears the clean settings & turns off the device. @@ -1098,25 +1163,25 @@ TEST(TestSharpAcClass, Clean) { ac.setPower(false, true); EXPECT_EQ( "Model: 1 (A907), Power: Off, Mode: 2 (Cool), Temp: 25C, Fan: 7 (High), " - "Turbo: Off, Swing(V) Toggle: Off, Ion: Off, Econo: -, Clean: Off", + "Swing(V): 0 (N/A), Turbo: Off, Ion: Off, Econo: -, Clean: Off", ac.toString()); // Clean ON ac.setClean(true); EXPECT_EQ( "Model: 1 (A907), Power: On, Mode: 3 (Dry), Temp: 15C, Fan: 2 (Auto), " - "Turbo: Off, Swing(V) Toggle: Off, Ion: Off, Econo: -, Clean: On", + "Swing(V): 0 (N/A), Turbo: Off, Ion: Off, Econo: -, Clean: On", ac.toString()); // AC OFF ac.off(); EXPECT_EQ( "Model: 1 (A907), Power: Off, Mode: 2 (Cool), Temp: 25C, Fan: 7 (High), " - "Turbo: Off, Swing(V) Toggle: Off, Ion: Off, Econo: -, Clean: Off", + "Swing(V): 0 (N/A), Turbo: Off, Ion: Off, Econo: -, Clean: Off", ac.toString()); // AC ON (Mode Cool, Temp 25, Ion OFF, Fan 7) ac.on(); EXPECT_EQ( "Model: 1 (A907), Power: On, Mode: 2 (Cool), Temp: 25C, Fan: 7 (High), " - "Turbo: Off, Swing(V) Toggle: Off, Ion: Off, Econo: -, Clean: Off", + "Swing(V): 0 (N/A), Turbo: Off, Ion: Off, Econo: -, Clean: Off", ac.toString()); } @@ -1126,7 +1191,7 @@ TEST(TestSharpAcClass, Issue1309) { ac.stateReset(); EXPECT_EQ( "Model: 1 (A907), Power: Off, Mode: 0 (Auto), Temp: 15C, Fan: 0 (UNKNOWN), " - "Turbo: Off, Swing(V) Toggle: Off, Ion: Off, Econo: -, Clean: Off", + "Swing(V): 0 (N/A), Turbo: Off, Ion: Off, Econo: -, Clean: Off", ac.toString()); const uint8_t issue1309_on[13] = { @@ -1135,7 +1200,7 @@ TEST(TestSharpAcClass, Issue1309) { ac.setRaw(issue1309_on); EXPECT_EQ( "Model: 2 (A705), Power: On, Mode: 2 (Cool), Temp: 16C, Fan: 2 (Auto), " - "Turbo: Off, Swing(V) Toggle: Off, Ion: Off, Light: -, Clean: Off", + "Swing(V): 0 (N/A), Turbo: Off, Ion: Off, Light: -, Clean: Off", ac.toString()); EXPECT_STATE_EQ(issue1309_on, ac.getRaw(), kSharpAcBits); @@ -1147,7 +1212,7 @@ TEST(TestSharpAcClass, Issue1309) { ac.on(); EXPECT_EQ( "Model: 2 (A705), Power: On, Mode: 2 (Cool), Temp: 16C, Fan: 2 (Auto), " - "Turbo: Off, Swing(V) Toggle: Off, Ion: Off, Light: -, Clean: Off", + "Swing(V): 0 (N/A), Turbo: Off, Ion: Off, Light: -, Clean: Off", ac.toString()); } @@ -1200,13 +1265,13 @@ TEST(TestSharpAcClass, Issue1387Power) { EXPECT_STATE_EQ(real_off, ac.getRaw(), kSharpAcBits); EXPECT_EQ( "Model: 3 (A903), Power: Off, Mode: 2 (Cool), Temp: 27C, Fan: 3 (Low), " - "Turbo: Off, Swing(V) Toggle: Off, Ion: On, Light: -, Clean: Off", + "Swing(V): 0 (N/A), Turbo: Off, Ion: On, Light: -, Clean: Off", ac.toString()); // Create the same off state. ac.setPower(true, ac.getPower()); EXPECT_STATE_EQ(real_on, ac.getRaw(), kSharpAcBits); EXPECT_EQ( "Model: 3 (A903), Power: On, Mode: 2 (Cool), Temp: 27C, Fan: 3 (Low), " - "Turbo: Off, Swing(V) Toggle: Off, Ion: On, Light: -, Clean: Off", + "Swing(V): 0 (N/A), Turbo: Off, Ion: On, Light: -, Clean: Off", ac.toString()); } diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Tcl_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Tcl_test.cpp index da3fefc8c..b7ab5301f 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Tcl_test.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Tcl_test.cpp @@ -10,8 +10,18 @@ // General housekeeping TEST(TestTcl112Ac, Housekeeping) { - ASSERT_EQ("TCL112AC", typeToString(TCL112AC)); - ASSERT_TRUE(hasACState(TCL112AC)); + ASSERT_EQ("TCL112AC", typeToString(decode_type_t::TCL112AC)); + ASSERT_EQ(decode_type_t::TCL112AC, strToDecodeType("TCL112AC")); + ASSERT_TRUE(hasACState(decode_type_t::TCL112AC)); + ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::TCL112AC)); + ASSERT_EQ(kTcl112AcBits, IRsend::defaultBits(decode_type_t::TCL112AC)); + ASSERT_EQ(kNoRepeat, IRsend::minRepeats(decode_type_t::TCL112AC)); + ASSERT_EQ(tcl_ac_remote_model_t::TAC09CHSD, IRac::strToModel("TAC09CHSD")); + ASSERT_EQ(irutils::modelToStr(decode_type_t::TCL112AC, + tcl_ac_remote_model_t::TAC09CHSD), "TAC09CHSD"); + ASSERT_EQ(tcl_ac_remote_model_t::GZ055BE1, IRac::strToModel("GZ055BE1")); + ASSERT_EQ(irutils::modelToStr(decode_type_t::TCL112AC, + tcl_ac_remote_model_t::GZ055BE1), "GZ055BE1"); } // Tests for decodeTcl112Ac(). @@ -63,9 +73,10 @@ TEST(TestDecodeTcl112Ac, DecodeRealExample) { EXPECT_EQ(kTcl112AcBits, irsend.capture.bits); EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); EXPECT_EQ( - "Type: 1, Power: On, Mode: 3 (Cool), Temp: 24C, Fan: 0 (Auto), " - "Econo: Off, Health: Off, Turbo: Off, Swing(H): Off, Swing(V): Off, " - "Light: On", + "Model: 1 (TAC09CHSD), Type: 1, Power: On, Mode: 3 (Cool), Temp: 24C, " + "Fan: 0 (Auto), Swing(V): 0 (Auto), Swing(H): Off, " + "Econo: Off, Health: Off, Turbo: Off, Light: On, " + "On Timer: Off, Off Timer: Off", IRAcUtils::resultAcToString(&irsend.capture)); } @@ -106,27 +117,31 @@ TEST(TestTcl112AcClass, Temperature) { IRTcl112Ac ac(kGpioUnused); ac.setRaw(temp16C); EXPECT_EQ( - "Type: 1, Power: On, Mode: 3 (Cool), Temp: 16C, Fan: 0 (Auto), " - "Econo: Off, Health: Off, Turbo: Off, Swing(H): Off, Swing(V): Off, " - "Light: On", + "Model: 1 (TAC09CHSD), Type: 1, Power: On, Mode: 3 (Cool), Temp: 16C, " + "Fan: 0 (Auto), Swing(V): 0 (Auto), Swing(H): Off, " + "Econo: Off, Health: Off, Turbo: Off, Light: On, " + "On Timer: Off, Off Timer: Off", ac.toString()); ac.setRaw(temp16point5C); EXPECT_EQ( - "Type: 1, Power: On, Mode: 3 (Cool), Temp: 16.5C, Fan: 0 (Auto), " - "Econo: Off, Health: Off, Turbo: Off, Swing(H): Off, Swing(V): Off, " - "Light: On", + "Model: 1 (TAC09CHSD), Type: 1, Power: On, Mode: 3 (Cool), Temp: 16.5C, " + "Fan: 0 (Auto), Swing(V): 0 (Auto), Swing(H): Off, " + "Econo: Off, Health: Off, Turbo: Off, Light: On, " + "On Timer: Off, Off Timer: Off", ac.toString()); ac.setRaw(temp19point5C); EXPECT_EQ( - "Type: 1, Power: On, Mode: 3 (Cool), Temp: 19.5C, Fan: 0 (Auto), " - "Econo: Off, Health: Off, Turbo: Off, Swing(H): Off, Swing(V): Off, " - "Light: On", + "Model: 1 (TAC09CHSD), Type: 1, Power: On, Mode: 3 (Cool), Temp: 19.5C, " + "Fan: 0 (Auto), Swing(V): 0 (Auto), Swing(H): Off, " + "Econo: Off, Health: Off, Turbo: Off, Light: On, " + "On Timer: Off, Off Timer: Off", ac.toString()); ac.setRaw(temp31C); EXPECT_EQ( - "Type: 1, Power: On, Mode: 3 (Cool), Temp: 31C, Fan: 0 (Auto), " - "Econo: Off, Health: Off, Turbo: Off, Swing(H): Off, Swing(V): Off, " - "Light: On", + "Model: 1 (TAC09CHSD), Type: 1, Power: On, Mode: 3 (Cool), Temp: 31C, " + "Fan: 0 (Auto), Swing(V): 0 (Auto), Swing(H): Off, " + "Econo: Off, Health: Off, Turbo: Off, Light: On, " + "On Timer: Off, Off Timer: Off", ac.toString()); ac.setTemp(kTcl112AcTempMin); @@ -206,9 +221,10 @@ TEST(TestTcl112AcClass, OperatingMode) { 0x07, 0x00, 0x00, 0x00, 0x00, 0x80, 0x48}; ac.setRaw(automode); EXPECT_EQ( - "Type: 1, Power: On, Mode: 8 (Auto), Temp: 24C, Fan: 0 (Auto), " - "Econo: Off, Health: Off, Turbo: Off, Swing(H): Off, Swing(V): Off, " - "Light: On", + "Model: 1 (TAC09CHSD), Type: 1, Power: On, Mode: 8 (Auto), Temp: 24C, " + "Fan: 0 (Auto), Swing(V): 0 (Auto), Swing(H): Off, " + "Econo: Off, Health: Off, Turbo: Off, Light: On, " + "On Timer: Off, Off Timer: Off", ac.toString()); } @@ -236,9 +252,10 @@ TEST(TestTcl112AcClass, Power) { 0x0F, 0x00, 0x00, 0x00, 0x00, 0x80, 0xCB}; ac.setRaw(on); EXPECT_EQ( - "Type: 1, Power: On, Mode: 3 (Cool), Temp: 16C, Fan: 0 (Auto), " - "Econo: Off, Health: Off, Turbo: Off, Swing(H): Off, Swing(V): Off, " - "Light: On", + "Model: 1 (TAC09CHSD), Type: 1, Power: On, Mode: 3 (Cool), Temp: 16C, " + "Fan: 0 (Auto), Swing(V): 0 (Auto), Swing(H): Off, " + "Econo: Off, Health: Off, Turbo: Off, Light: On, " + "On Timer: Off, Off Timer: Off", ac.toString()); const uint8_t off[kTcl112AcStateLength] = { @@ -246,9 +263,10 @@ TEST(TestTcl112AcClass, Power) { 0x07, 0x40, 0x00, 0x00, 0x00, 0x80, 0xCB}; ac.setRaw(off); EXPECT_EQ( - "Type: 1, Power: Off, Mode: 3 (Cool), Temp: 24C, Fan: 0 (Auto), " - "Econo: Off, Health: Off, Turbo: Off, Swing(H): Off, Swing(V): Off, " - "Light: On", + "Model: 1 (TAC09CHSD), Type: 1, Power: Off, Mode: 3 (Cool), Temp: 24C, " + "Fan: 0 (Auto), Swing(V): 0 (Auto), Swing(H): Off, " + "Econo: Off, Health: Off, Turbo: Off, Light: On, " + "On Timer: Off, Off Timer: Off", ac.toString()); } @@ -263,15 +281,17 @@ TEST(TestTcl112AcClass, Checksum) { EXPECT_EQ(0xCB, ac.calcChecksum(temp16C)); ac.setRaw(temp16C); EXPECT_EQ( - "Type: 1, Power: On, Mode: 3 (Cool), Temp: 16C, Fan: 0 (Auto), " - "Econo: Off, Health: Off, Turbo: Off, Swing(H): Off, Swing(V): Off, " - "Light: On", + "Model: 1 (TAC09CHSD), Type: 1, Power: On, Mode: 3 (Cool), Temp: 16C, " + "Fan: 0 (Auto), Swing(V): 0 (Auto), Swing(H): Off, " + "Econo: Off, Health: Off, Turbo: Off, Light: On, " + "On Timer: Off, Off Timer: Off", ac.toString()); ac.setRaw(temp31C); EXPECT_EQ( - "Type: 1, Power: On, Mode: 3 (Cool), Temp: 31C, Fan: 0 (Auto), " - "Econo: Off, Health: Off, Turbo: Off, Swing(H): Off, Swing(V): Off, " - "Light: On", + "Model: 1 (TAC09CHSD), Type: 1, Power: On, Mode: 3 (Cool), Temp: 31C, " + "Fan: 0 (Auto), Swing(V): 0 (Auto), Swing(H): Off, " + "Econo: Off, Health: Off, Turbo: Off, Light: On, " + "On Timer: Off, Off Timer: Off", ac.toString()); EXPECT_EQ(0xBC, ac.calcChecksum(temp31C)); @@ -337,12 +357,22 @@ TEST(TestTcl112AcClass, SwingVertical) { IRTcl112Ac ac(kGpioUnused); ac.begin(); - ac.setSwingVertical(true); - EXPECT_TRUE(ac.getSwingVertical()); - ac.setSwingVertical(false); - EXPECT_EQ(false, ac.getSwingVertical()); - ac.setSwingVertical(true); - EXPECT_TRUE(ac.getSwingVertical()); + ac.setSwingVertical(kTcl112AcSwingVOff); + EXPECT_EQ(kTcl112AcSwingVOff, ac.getSwingVertical()); + ac.setSwingVertical(kTcl112AcSwingVOn); + EXPECT_EQ(kTcl112AcSwingVOn, ac.getSwingVertical()); + ac.setSwingVertical(kTcl112AcSwingVHigh); + EXPECT_EQ(kTcl112AcSwingVHigh, ac.getSwingVertical()); + ac.setSwingVertical(kTcl112AcSwingVOff); + EXPECT_EQ(kTcl112AcSwingVOff, ac.getSwingVertical()); + ac.setSwingVertical(0xFF); // Unused value so shouldn't change from previous. + EXPECT_EQ(kTcl112AcSwingVOff, ac.getSwingVertical()); + + const uint8_t highest[kTcl112AcStateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03, + 0x0F, 0x08, 0x00, 0x00, 0x00, 0x00, 0x53}; + ac.setRaw(highest); + EXPECT_EQ(kTcl112AcSwingVHighest, ac.getSwingVertical()); } TEST(TestTcl112AcClass, Turbo) { @@ -405,6 +435,7 @@ TEST(TestTcl112AcClass, Quiet_Mute) { TEST(TestTcl112AcClass, toCommon) { IRTcl112Ac ac(kGpioUnused); + ac.setModel(tcl_ac_remote_model_t::TAC09CHSD); ac.setPower(true); ac.setMode(kTcl112AcCool); ac.setTemp(20); @@ -418,7 +449,7 @@ TEST(TestTcl112AcClass, toCommon) { ac.setQuiet(false); // Now test it. ASSERT_EQ(decode_type_t::TCL112AC, ac.toCommon().protocol); - ASSERT_EQ(-1, ac.toCommon().model); + ASSERT_EQ(1, ac.toCommon().model); ASSERT_TRUE(ac.toCommon().power); ASSERT_TRUE(ac.toCommon().celsius); ASSERT_EQ(20, ac.toCommon().degrees); @@ -485,9 +516,10 @@ TEST(TestDecodeTcl112Ac, Issue744) { IRTcl112Ac ac(kGpioUnused); ac.setRaw(irsend.capture.state); EXPECT_EQ( - "Type: 1, Power: On, Mode: 3 (Cool), Temp: 23C, Fan: 0 (Auto), " - "Econo: Off, Health: Off, Turbo: Off, Swing(H): Off, Swing(V): Off, " - "Light: On", + "Model: 1 (TAC09CHSD), Type: 1, Power: On, Mode: 3 (Cool), Temp: 23C, " + "Fan: 0 (Auto), Swing(V): 0 (Auto), Swing(H): Off, " + "Econo: Off, Health: Off, Turbo: Off, Light: On, " + "On Timer: Off, Off Timer: Off", ac.toString()); } @@ -527,7 +559,7 @@ TEST(TestDecodeTcl112Ac, Issue1528) { EXPECT_EQ(kTcl112AcBits, irsend.capture.bits); EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); EXPECT_EQ( - "Type: 2, Quiet: On", + "Model: 1 (TAC09CHSD), Type: 2, Quiet: On", IRAcUtils::resultAcToString(&irsend.capture)); } @@ -536,7 +568,6 @@ TEST(TestTcl112AcClass, SendingQuiet) { IRTcl112Ac ac(kGpioUnused); IRrecv capture(kGpioUnused); - ac.begin(); ac.on(); ac.setTemp(24); @@ -559,16 +590,116 @@ TEST(TestTcl112AcClass, SendingQuiet) { ASSERT_EQ(TCL112AC, ac._irsend.capture.decode_type); ASSERT_EQ(kTcl112AcBits, ac._irsend.capture.bits); ASSERT_EQ( - "Type: 2, Quiet: On", + "Model: 1 (TAC09CHSD), Type: 2, Quiet: On", IRAcUtils::resultAcToString(&ac._irsend.capture)); // Second message. // TCL112 uses the Mitsubishi112 decoder. // Skip first message. EXPECT_TRUE(capture.decodeMitsubishi112(&ac._irsend.capture, 229)); - ASSERT_EQ(TCL112AC, ac._irsend.capture.decode_type); - ASSERT_EQ(kTcl112AcBits, ac._irsend.capture.bits); + EXPECT_EQ(TCL112AC, ac._irsend.capture.decode_type); + EXPECT_EQ(kTcl112AcBits, ac._irsend.capture.bits); ASSERT_EQ( - "Type: 1, Power: On, Mode: 3 (Cool), Temp: 24C, Fan: 0 (Auto), " - "Econo: Off, Health: Off, Turbo: Off, Swing(H): Off, Swing(V): Off, " - "Light: Off", IRAcUtils::resultAcToString(&ac._irsend.capture)); + "Model: 1 (TAC09CHSD), Type: 1, Power: On, Mode: 3 (Cool), Temp: 24C, " + "Fan: 0 (Auto), Swing(V): 0 (Auto), Swing(H): Off, " + "Econo: Off, Health: Off, Turbo: Off, Light: Off, " + "On Timer: Off, Off Timer: Off", + IRAcUtils::resultAcToString(&ac._irsend.capture)); +} + +TEST(TestTcl112AcClass, isTcl) { + const uint8_t tcl_temp16C[kTcl112AcStateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03, + 0x0F, 0x00, 0x00, 0x00, 0x00, 0x80, 0xCB}; + EXPECT_TRUE(IRTcl112Ac::isTcl(tcl_temp16C)); + const uint8_t tcl_temp31C[kTcl112AcStateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xBC}; + EXPECT_TRUE(IRTcl112Ac::isTcl(tcl_temp31C)); + const uint8_t issue1528[kTcl112AcStateLength] = { + 0x23, 0xCB, 0x26, 0x02, 0x00, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85}; + EXPECT_TRUE(IRTcl112Ac::isTcl(issue1528)); + // Ref: https://cociweb.info/container/hvac_ir_recapture_2719.log + const uint8_t teknopoint[14] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03, + 0x0F, 0x38, 0x00, 0x00, 0x00, 0x00, 0x83}; + EXPECT_FALSE(IRTcl112Ac::isTcl(teknopoint)); +} + +TEST(TestTcl112AcClass, Timers) { + IRTcl112Ac ac(kGpioUnused); + + ac.stateReset(); + ac.setOnTimer(0); + ac.setOffTimer(0); + EXPECT_EQ(0, ac.getOnTimer()); + EXPECT_EQ(0, ac.getOffTimer()); + EXPECT_FALSE(ac._.TimerIndicator); + EXPECT_FALSE(ac._.OnTimerEnabled); + EXPECT_FALSE(ac._.OffTimerEnabled); + + ac.setOnTimer(7 * 60); + EXPECT_EQ(7 * 60, ac.getOnTimer()); + EXPECT_TRUE(ac._.TimerIndicator); + EXPECT_TRUE(ac._.OnTimerEnabled); + EXPECT_FALSE(ac._.OffTimerEnabled); + + ac.setOnTimer(0); + EXPECT_EQ(0, ac.getOnTimer()); + EXPECT_FALSE(ac._.TimerIndicator); + EXPECT_FALSE(ac._.OnTimerEnabled); + EXPECT_FALSE(ac._.OffTimerEnabled); + + ac.setOffTimer(13 * 60); // Beyond max. + EXPECT_EQ(12 * 60, ac.getOffTimer()); + EXPECT_TRUE(ac._.TimerIndicator); + EXPECT_FALSE(ac._.OnTimerEnabled); + EXPECT_TRUE(ac._.OffTimerEnabled); + + ac.setOffTimer(0); + EXPECT_EQ(0, ac.getOffTimer()); + EXPECT_FALSE(ac._.TimerIndicator); + EXPECT_FALSE(ac._.OnTimerEnabled); + EXPECT_FALSE(ac._.OffTimerEnabled); + + // Real messages/states + // Per https://github.com/crankyoldgit/IRremoteESP8266/issues/1486#issuecomment-917545485 + + const uint8_t ontimer_1h[14] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x34, 0x03, + 0x00, 0x78, 0x00, 0x06, 0x00, 0x00, 0xCA}; + ac.setRaw(ontimer_1h); + EXPECT_EQ(60, ac.getOnTimer()); + EXPECT_TRUE(ac._.TimerIndicator); + EXPECT_TRUE(ac._.OnTimerEnabled); + EXPECT_FALSE(ac._.OffTimerEnabled); + + const uint8_t ontimer_4h[14] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x34, 0x03, + 0x00, 0x78, 0x00, 0x18, 0x00, 0x00, 0xDC}; + ac.setRaw(ontimer_4h); + EXPECT_EQ(240, ac.getOnTimer()); + EXPECT_TRUE(ac._.TimerIndicator); + EXPECT_TRUE(ac._.OnTimerEnabled); + EXPECT_FALSE(ac._.OffTimerEnabled); + EXPECT_EQ( + "Model: 2 (GZ055BE1), Type: 1, Power: On, Mode: 3 (Cool), Temp: 31C, " + "Fan: 0 (Auto), Swing(V): 7 (Swing), " + "On Timer: 04:00, Off Timer: Off", + ac.toString()); + + const uint8_t offtimer_2h[14] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x2C, 0x08, + 0x07, 0x78, 0x0C, 0x00, 0x00, 0x00, 0xD4}; + + ac.setRaw(offtimer_2h); + EXPECT_EQ(120, ac.getOffTimer()); + EXPECT_TRUE(ac._.TimerIndicator); + EXPECT_FALSE(ac._.OnTimerEnabled); + EXPECT_TRUE(ac._.OffTimerEnabled); + EXPECT_EQ( + "Model: 2 (GZ055BE1), Type: 1, Power: On, Mode: 8 (Auto), Temp: 24C, " + "Fan: 0 (Auto), Swing(V): 7 (Swing), " + "On Timer: Off, Off Timer: 02:00", + ac.toString()); } diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Teknopoint_test.cpp b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Teknopoint_test.cpp index 009b2a41b..74f29d146 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Teknopoint_test.cpp +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/test/ir_Teknopoint_test.cpp @@ -44,7 +44,9 @@ TEST(TestDecodeTeknopoint, RealExample) { ASSERT_EQ(kTeknopointBits, irsend.capture.bits); EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); EXPECT_EQ( - "", + "Model: 2 (GZ055BE1), Type: 1, Power: On, Mode: 3 (Cool), Temp: 16C, " + "Fan: 0 (Auto), Swing(V): 1 (Highest), " + "On Timer: Off, Off Timer: Off", IRAcUtils::resultAcToString(&irsend.capture)); } @@ -67,7 +69,9 @@ TEST(TestDecodeTeknopoint, SyntheticExample) { ASSERT_EQ(kTeknopointBits, irsend.capture.bits); EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); EXPECT_EQ( - "", + "Model: 2 (GZ055BE1), Type: 1, Power: On, Mode: 3 (Cool), Temp: 16C, " + "Fan: 0 (Auto), Swing(V): 1 (Highest), " + "On Timer: Off, Off Timer: Off", IRAcUtils::resultAcToString(&irsend.capture)); EXPECT_EQ( @@ -95,7 +99,7 @@ TEST(TestUtils, Housekeeping) { ASSERT_EQ("TEKNOPOINT", typeToString(decode_type_t::TEKNOPOINT)); ASSERT_EQ(decode_type_t::TEKNOPOINT, strToDecodeType("TEKNOPOINT")); ASSERT_TRUE(hasACState(decode_type_t::TEKNOPOINT)); - ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::TEKNOPOINT)); + ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::TEKNOPOINT)); ASSERT_EQ(kTeknopointBits, IRsend::defaultBits(decode_type_t::TEKNOPOINT)); ASSERT_EQ(kNoRepeat, IRsend::minRepeats(decode_type_t::TEKNOPOINT)); } diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/Makefile b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/Makefile index b30d1207c..15f192efd 100644 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/Makefile +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/Makefile @@ -1,7 +1,11 @@ # SYNOPSIS: # -# make [all] - makes everything. -# make clean - removes all files generated by make. +# make [all] - makes everything. +# make TARGET - makes the given target. +# make run_tests - makes everything and runs all test +# make run-% - run specific test file (exclude .py) +# replace % with given test file +# make clean - removes all files generated by make. # Please tweak the following variable definitions as needed by your # project, except GTEST_HEADERS, which you can use in your own targets @@ -37,6 +41,10 @@ run_tests : all echo "PASS: \o/ \o/ All unit tests passed. \o/ \o/"; \ fi +run-% : all + echo "RUNNING: $*"; \ + python3 ./$*.py; + clean : rm -f *.o *.pyc gc_decode mode2_decode diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/auto_analyse_raw_data.py b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/auto_analyse_raw_data.py index aa5c990a9..e061d3c42 100755 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/auto_analyse_raw_data.py +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/auto_analyse_raw_data.py @@ -85,6 +85,7 @@ class RawIRMessage(): bits = len(binary_str) rev_binary_str = binary_str[::-1] rev_num = int(rev_binary_str, 2) + # pylint: disable=C0209 self.output.write("\n Bits: %d\n" " Hex: %s (MSB first)\n" " %s (LSB first)\n" @@ -95,22 +96,21 @@ class RawIRMessage(): (bits, ("0x{0:0%dX}" % (bits / 4)).format(num), ("0x{0:0%dX}" % (bits / 4)).format(rev_num), num, rev_num, binary_str, rev_binary_str)) + # pylint: enable=C0209 def add_data_code(self, bin_str, name="", footer=True): """Add the common "data" sequence of code to send the bulk of a message.""" # pylint: disable=no-self-use code = [] nbits = len(bin_str) - code.append(" // Data Section #%d" % self.section_count) - code.append(" // e.g. data = 0x%X, nbits = %d" % (int(bin_str, 2), - nbits)) - code.append(" sendData(k%sBitMark, k%sOneSpace, k%sBitMark, " - "k%sZeroSpace, send_data, %d, true);" % - (name, name, name, name, nbits)) - code.append(" send_data >>= %d;" % nbits) + code.append(f" // Data Section #{self.section_count}") + code.append(f" // e.g. data = 0x{int(bin_str, 2):X}, nbits = {nbits}") + code.append(f" sendData(k{name}BitMark, k{name}OneSpace, k{name}BitMark," + f" k{name}ZeroSpace, send_data, {nbits}, true);") + code.append(f" send_data >>= {nbits};") if footer: code.append(" // Footer") - code.append(" mark(k%sBitMark);" % name) + code.append(f" mark(k{name}BitMark);") return code def add_data_decode_code(self, bin_str, name="", footer=True): @@ -120,21 +120,20 @@ class RawIRMessage(): nbits = len(bin_str) code.extend([ "", - " // Data Section #%d" % self.section_count, - " // e.g. data_result.data = 0x%X, nbits = %d" % (int(bin_str, 2), - nbits), - " data_result = matchData(&(results->rawbuf[offset]), %s," % nbits, - " k%sBitMark, k%sOneSpace," % (name, name), - " k%sBitMark, k%sZeroSpace);" % (name, name), + f" // Data Section #{self.section_count}", + f" // e.g. data_result.data = 0x{int(bin_str, 2):X}, nbits = {nbits}", + f" data_result = matchData(&(results->rawbuf[offset]), {nbits},", + f" k{name}BitMark, k{name}OneSpace,", + f" k{name}BitMark, k{name}ZeroSpace);", " offset += data_result.used;", " if (data_result.success == false) return false; // Fail", - " data <<= %s; // Make room for the new bits of data." % nbits, + f" data <<= {nbits}; // Make room for the new bits of data.", " data |= data_result.data;"]) if footer: code.extend([ "", " // Footer", - " if (!matchMark(results->rawbuf[offset++], k%sBitMark))" % name, + f" if (!matchMark(results->rawbuf[offset++], k{name}BitMark))", " return false;"]) return code @@ -148,26 +147,28 @@ class RawIRMessage(): ambles = {} firstmark = ambles.get("firstmark", 0) firstspace = ambles.get("firstspace", 0) - lastmark = ambles.get("lastmark", "k%sBitMark" % name) + lastmark = ambles.get("lastmark", f"k{name}BitMark") lastspace = ambles.get("lastspace", "kDefaultMessageGap") - code.append( - " // Data Section #%d" % self.section_count) + code.append(f" // Data Section #{self.section_count}") if nbits % 8: code.append(" // DANGER: Nr. of bits is not a multiple of 8. " "This section won't work!") code.extend([ " // e.g.", - " // bits = %d; bytes = %d;" % (nbits, nbytes), + f" // bits = {nbits}; bytes = {int(nbytes)};", + # pylint: disable=C0209 " // *(data + pos) = {0x%s};" % ( ", 0x".join("%02X" % int(bin_str[i:i + 8], 2) for i in range(0, len(bin_str), 8))), - " sendGeneric(%s, %s," % (firstmark, firstspace), - " k%sBitMark, k%sOneSpace," % (name, name), - " k%sBitMark, k%sZeroSpace," % (name, name), - " %s, %s," % (lastmark, lastspace), - " data + pos, %d, // Bytes" % nbytes, - " k%sFreq, true, kNoRepeat, kDutyDefault);" % name, - " pos += %d; // Adjust by how many bytes of data we sent" % nbytes]) + # pylint: enable=C0209 + f" sendGeneric({firstmark}, {firstspace},", + f" k{name}BitMark, k{name}OneSpace,", + f" k{name}BitMark, k{name}ZeroSpace,", + f" {lastmark}, {lastspace},", + f" data + pos, {int(nbytes)}, // Bytes", + f" k{name}Freq, true, kNoRepeat, kDutyDefault);", + f" pos += {int(nbytes)};" + f" // Adjust by how many bytes of data we sent"]) return code def add_data_byte_decode_code(self, bin_str, name="", ambles=None): @@ -183,36 +184,37 @@ class RawIRMessage(): ambles = {} firstmark = ambles.get("firstmark", 0) firstspace = ambles.get("firstspace", 0) - lastmark = ambles.get("lastmark", "k%sBitMark" % name) + lastmark = ambles.get("lastmark", f"k{name}BitMark") lastspace = ambles.get("lastspace", "kDefaultMessageGap") code.extend([ "", - " // Data Section #%d" % self.section_count, + f" // Data Section #{self.section_count}", " // e.g.", - " // bits = %d; bytes = %d;" % (nbits, nbytes), + f" // bits = {nbits}; bytes = {int(nbytes)};", + # pylint: disable=C0209 " // *(results->state + pos) = {0x%s};" % ( ", 0x".join("%02X" % int(bin_str[i:i + 8], 2) for i in range(0, len(bin_str), 8))), + # pylint: enable=C0209 " used = matchGeneric(results->rawbuf + offset, results->state + pos,", - " results->rawlen - offset, %d," % nbits, - " %s, %s," % (firstmark, firstspace), - " k%sBitMark, k%sOneSpace," % (name, name), - " k%sBitMark, k%sZeroSpace," % (name, name), - " %s, %s, true);" % (lastmark, lastspace), + f" results->rawlen - offset, {nbits},", + f" {firstmark}, {firstspace},", + f" k{name}BitMark, k{name}OneSpace,", + f" k{name}BitMark, k{name}ZeroSpace,", + f" {lastmark}, {lastspace}, true);", " if (used == 0) return false; // We failed to find any data.", " offset += used; // Adjust for how much of the message we read.", - " pos += %d; // Adjust by how many bytes of data we read" % nbytes]) + f" pos += {int(nbytes)};" + " // Adjust by how many bytes of data we read"]) return code def _calc_values(self): """Calculate the values which describe the standard timings for the protocol.""" if self.verbose: - self.output.write("Potential Mark Candidates:\n" - "%s\n" - "Potential Space Candidates:\n" - "%s\n" % (str(self.marks), str(self.spaces))) + self.output.write(f"Potential Mark Candidates:\n{self.marks}\n" + f"Potential Space Candidates:\n{self.spaces}\n") # The bit mark is likely to be the smallest mark. self.bit_mark = self.marks[-1] if len(self.marks) > 2: # Possible leader mark? @@ -305,8 +307,8 @@ def convert_rawdata(data_str): results.append(int(timing)) except ValueError as non_numeric: raise ValueError( - "Raw Data contains a non-numeric value of '%s'." % - timing) from non_numeric + f"Raw Data contains a non-numeric value of '{timing}'." + ) from non_numeric return results @@ -326,35 +328,33 @@ def dump_constants(message, defines, name="", output=sys.stdout): zero_space = avg_list(message.space_buckets[message.zero_space]) output.write("Guessing key value:\n" - "k%sHdrMark = %d\n" - "k%sHdrSpace = %d\n" - "k%sBitMark = %d\n" - "k%sOneSpace = %d\n" - "k%sZeroSpace = %d\n" % (name, hdr_mark, name, hdr_space, - name, bit_mark, name, one_space, - name, zero_space)) - defines.append("const uint16_t k%sHdrMark = %d;" % (name, hdr_mark)) - defines.append("const uint16_t k%sBitMark = %d;" % (name, bit_mark)) - defines.append("const uint16_t k%sHdrSpace = %d;" % (name, hdr_space)) - defines.append("const uint16_t k%sOneSpace = %d;" % (name, one_space)) - defines.append("const uint16_t k%sZeroSpace = %d;" % (name, zero_space)) + f"k{name}HdrMark = {hdr_mark}\n" + f"k{name}HdrSpace = {hdr_space}\n" + f"k{name}BitMark = {bit_mark}\n" + f"k{name}OneSpace = {one_space}\n" + f"k{name}ZeroSpace = {zero_space}\n") + defines.append(f"const uint16_t k{name}HdrMark = {hdr_mark};") + defines.append(f"const uint16_t k{name}BitMark = {bit_mark};") + defines.append(f"const uint16_t k{name}HdrSpace = {hdr_space};") + defines.append(f"const uint16_t k{name}OneSpace = {one_space};") + defines.append(f"const uint16_t k{name}ZeroSpace = {zero_space};") if ldr_mark: - output.write("k%sLdrMark = %d\n" % (name, ldr_mark)) - defines.append("const uint16_t k%sLdrMark = %d;" % (name, ldr_mark)) + output.write(f"k{name}LdrMark = {ldr_mark}\n") + defines.append(f"const uint16_t k{name}LdrMark = {ldr_mark};") avg_gaps = [avg_list(message.space_buckets[x]) for x in message.gaps] if len(message.gaps) == 1: - output.write("k%sSpaceGap = %d\n" % (name, avg_gaps[0])) - defines.append("const uint16_t k%sSpaceGap = %d;" % (name, avg_gaps[0])) + output.write(f"k{name}SpaceGap = {avg_gaps[0]}\n") + defines.append(f"const uint16_t k{name}SpaceGap = {avg_gaps[0]};") else: count = 0 for gap in avg_gaps: # We probably (still) have a gap in the protocol. count = count + 1 - output.write("k%sSpaceGap%d = %d\n" % (name, count, gap)) - defines.append("const uint16_t k%sSpaceGap%d = %d;" % (name, count, gap)) - defines.append("const uint16_t k%sFreq = 38000; " - "// Hz. (Guessing the most common frequency.)" % name) + output.write(f"k{name}SpaceGap{count} = {gap}\n") + defines.append(f"const uint16_t k{name}SpaceGap{count} = {gap};") + defines.append(f"const uint16_t k{name}Freq = 38000; " + "// Hz. (Guessing the most common frequency.)") def parse_and_report(rawdata_str, margin, gen_code=False, name="", @@ -374,7 +374,7 @@ def parse_and_report(rawdata_str, margin, gen_code=False, name="", # Parse the input. rawdata = convert_rawdata(rawdata_str) - output.write("Found %d timing entries.\n" % len(rawdata)) + output.write(f"Found {len(rawdata)} timing entries.\n") message = RawIRMessage(margin, rawdata, output) output.write("\nGuessing encoding type:\n") @@ -410,17 +410,17 @@ def decode_data(message, defines, code, name="", output=sys.stdout): code["sendcomhead"].extend([ "", - "#if SEND_%s" % def_name.upper(), + f"#if SEND_{def_name.upper()}", SAFE64NOTE, - "/// Send a %s formatted message." % name, + f"/// Send a {name} formatted message.", "/// Status: ALPHA / Untested."]) code["send"].extend([ "/// @param[in] data containing the IR command.", - "/// @param[in] nbits Nr. of bits to send. usually k%sBits" % name, + f"/// @param[in] nbits Nr. of bits to send. usually k{name}Bits", "/// @param[in] repeat Nr. of times the message is to be repeated.", - "void IRsend::send%s(const uint64_t data, const uint16_t" - " nbits, const uint16_t repeat) {" % def_name, - " enableIROut(k%sFreq);" % name, + f"void IRsend::send{def_name}(const uint64_t data, const uint16_t" + " nbits, const uint16_t repeat) {", + f" enableIROut(k{name}Freq);", " for (uint16_t r = 0; r <= repeat; r++) {", " uint64_t send_data = data;"]) code["send64+"].extend([ @@ -431,21 +431,21 @@ def decode_data(message, defines, code, name="", output=sys.stdout): CODEGEN, "/// @endcode", "/// @param[in] nbytes Nr. of bytes of data in the array." - " (>=k%sStateLength)" % name, + f" (>=k{name}StateLength)", "/// @param[in] repeat Nr. of times the message is to be repeated.", - "void IRsend::send%s(const uint8_t data[], const uint16_t nbytes," - " const uint16_t repeat) {" % def_name, + f"void IRsend::send{def_name}(const uint8_t data[]," + " const uint16_t nbytes, const uint16_t repeat) {", " for (uint16_t r = 0; r <= repeat; r++) {", " uint16_t pos = 0;"]) code["sendcomfoot"].extend([ " }", "}", - "#endif // SEND_%s" % def_name.upper()]) + f"#endif // SEND_{def_name.upper()}"]) code["recvcomhead"].extend([ "", - "#if DECODE_%s" % def_name.upper(), + f"#if DECODE_{def_name.upper()}", SAFE64NOTE, - "/// Decode the supplied %s message." % name, + f"/// Decode the supplied {name} message.", "/// Status: ALPHA / Untested.", "/// @param[in,out] results Ptr to the data to decode &" " where to store the decode", @@ -456,11 +456,11 @@ def decode_data(message, defines, code, name="", output=sys.stdout): "/// @param[in] strict Flag indicating if we should perform strict" " matching.", "/// @return A boolean. True if it can decode it, false if it can't.", - "bool IRrecv::decode%s(decode_results *results, uint16_t offset," - " const uint16_t nbits, const bool strict) {" % def_name, - " if (results->rawlen < 2 * nbits + k%sOverhead - offset)" % name, + f"bool IRrecv::decode{def_name}(decode_results *results, uint16_t offset," + " const uint16_t nbits, const bool strict) {", + f" if (results->rawlen < 2 * nbits + k{name}Overhead - offset)", " return false; // Too short a message to match.", - " if (strict && nbits != k%sBits)" % name, + f" if (strict && nbits != k{name}Bits)", " return false;", ""]) code["recv"].extend([ @@ -472,7 +472,7 @@ def decode_data(message, defines, code, name="", output=sys.stdout): code["recvcomfoot"].extend([ " return true;", "}", - "#endif // DECODE_%s" % def_name.upper()]) + f"#endif // DECODE_{def_name.upper()}"]) # states are: # HM: Header/Leader mark @@ -496,24 +496,24 @@ def decode_data(message, defines, code, name="", output=sys.stdout): code["recv"].extend(message.add_data_decode_code(binary_value, name, False)) message.section_count = message.section_count + 1 - code_info["lastmark"] = "k%s%sdrMark" % (name, mark_type) + code_info["lastmark"] = f"k{name}{mark_type}drMark" total_bits = total_bits + binary_value - code_info["firstmark"] = "k%s%sdrMark" % (name, mark_type) + code_info["firstmark"] = f"k{name}{mark_type}drMark" binary_value = add_bit(binary_value, "reset") - output.write("k%s%sdrMark+" % (name, mark_type)) - code["send"].extend([" // %seader" % mark_type, - " mark(k%s%sdrMark);" % (name, mark_type)]) + output.write(f"k{name}{mark_type}drMark+") + code["send"].extend([f" // {mark_type}eader", + f" mark(k{name}{mark_type}drMark);"]) code["recv"].extend([ "", - " // %seader" % mark_type, - " if (!matchMark(results->rawbuf[offset++], k%s%sdrMark))" % ( - name, mark_type), + f" // {mark_type}eader", + " if (!matchMark(results->rawbuf[offset++]," + f" k{name}{mark_type}drMark))", " return false;"]) # Handle header spaces. elif message.is_hdr_space(usec) and not message.is_one_space(usec): if binary64_value: - code_info["lastspace"] = "k%sHdrSpace" % name + code_info["lastspace"] = f"k{name}HdrSpace" message.section_count = message.section_count - 1 code["send64+"].extend(message.add_data_byte_code(binary64_value, name, code_info)) @@ -529,39 +529,39 @@ def decode_data(message, defines, code, name="", output=sys.stdout): total_bits = total_bits + binary_value code["send"].extend(message.add_data_code(binary_value, name)) code["recv"].extend(message.add_data_decode_code(binary_value, name)) - code_info["lastspace"] = "k%sHdrSpace" % name + code_info["lastspace"] = f"k{name}HdrSpace" message.section_count = message.section_count + 1 binary_value = binary64_value = add_bit(binary_value, "reset") output.write("UNEXPECTED->") state = "HS" - output.write("k%sHdrSpace+" % name) - code["send"].append(" space(k%sHdrSpace);" % name) + output.write(f"k{name}HdrSpace+") + code["send"].append(f" space(k{name}HdrSpace);") code["recv"].extend([ - " if (!matchSpace(results->rawbuf[offset++], k%sHdrSpace))" % name, + f" if (!matchSpace(results->rawbuf[offset++], k{name}HdrSpace))", " return false;"]) - code_info["firstspace"] = "k%sHdrSpace" % name + code_info["firstspace"] = f"k{name}HdrSpace" # Handle bit marks. elif message.is_bit_mark(usec) and count % 2: if state not in ("HS", "BS"): - output.write("k%sBitMark(UNEXPECTED)" % name) + output.write(f"k{name}BitMark(UNEXPECTED)") state = "BM" # Handle "zero" spaces elif message.is_zero_space(usec): if state != "BM": - output.write("k%sZeroSpace(UNEXPECTED)" % name) + output.write(f"k{name}ZeroSpace(UNEXPECTED)") state = "BS" binary_value = binary64_value = add_bit(binary_value, 0, output) # Handle "one" spaces elif message.is_one_space(usec): if state != "BM": - output.write("k%sOneSpace(UNEXPECTED)" % name) + output.write(f"k{name}OneSpace(UNEXPECTED)") state = "BS" binary_value = binary64_value = add_bit(binary_value, 1, output) elif message.is_gap(usec): if state != "BM": output.write("UNEXPECTED->") - output.write("GAP(%d)" % usec) - code_info["lastspace"] = "k%sSpaceGap" % name + output.write(f"GAP({usec})") + code_info["lastspace"] = f"k{name}SpaceGap" if binary64_value: code["send64+"].extend(message.add_data_byte_code(binary64_value, name, code_info)) @@ -579,19 +579,19 @@ def decode_data(message, defines, code, name="", output=sys.stdout): " // Gap"]) code["send"].extend([" // Gap"]) if state == "BM": - code["send"].extend([" mark(k%sBitMark);" % name]) + code["send"].extend([f" mark(k{name}BitMark);"]) code["recv"].extend([ - " if (!matchMark(results->rawbuf[offset++], k%sBitMark))" % name, + f" if (!matchMark(results->rawbuf[offset++], k{name}BitMark))", " return false;"]) - code["send"].append(" space(k%sSpaceGap);" % name) + code["send"].append(f" space(k{name}SpaceGap);") code["recv"].extend([ - " if (!matchSpace(results->rawbuf[offset++], k%sSpaceGap))" % name, + f" if (!matchSpace(results->rawbuf[offset++], k{name}SpaceGap))", " return false;"]) total_bits = total_bits + binary_value binary_value = binary64_value = add_bit(binary_value, "reset") state = "GS" else: - output.write("UNKNOWN(%d)" % usec) + output.write(f"UNKNOWN({usec})") state = "UNK" count = count + 1 if binary64_value: @@ -611,7 +611,7 @@ def decode_data(message, defines, code, name="", output=sys.stdout): code["recv"].extend([ "", " // Success", - " results->decode_type = decode_type_t::%s;" % def_name.upper(), + f" results->decode_type = decode_type_t::{def_name.upper()};", " results->bits = nbits;", " results->value = data;", " results->command = 0;", @@ -619,19 +619,18 @@ def decode_data(message, defines, code, name="", output=sys.stdout): code["recv64+"].extend([ "", " // Success", - " results->decode_type = decode_type_t::%s;" % def_name.upper(), + f" results->decode_type = decode_type_t::{def_name.upper()};", " results->bits = nbits;"]) total_bits = total_bits + binary_value - output.write("\nTotal Nr. of suspected bits: %d\n" % len(total_bits)) - defines.append("const uint16_t k%sBits = %d;" - " // Move to IRremoteESP8266.h" % (name, len(total_bits))) + output.write(f"\nTotal Nr. of suspected bits: {len(total_bits)}\n") + defines.append(f"const uint16_t k{name}Bits = {len(total_bits)};" + " // Move to IRremoteESP8266.h") if len(total_bits) > 64: - defines.append("const uint16_t k%sStateLength = %d;" - " // Move to IRremoteESP8266.h" % - (name, len(total_bits) / 8)) - defines.append("const uint16_t k%sOverhead = %d;" % - (name, message.rawlen - 2 * len(total_bits))) + defines.append(f"const uint16_t k{name}StateLength = " + f"{int(len(total_bits) / 8)}; // Move to IRremoteESP8266.h") + defines.append(f"const uint16_t k{name}Overhead = " + f"{message.rawlen - 2 * len(total_bits)};") return total_bits @@ -645,9 +644,9 @@ def generate_code(defines, code, bits_str, name="", output=sys.stdout): output.write("\nGenerating a VERY rough code outline:\n\n" "// Copyright 2020 David Conran (crankyoldgit)\n" "/// @file\n" - "/// @brief Support for %s protocol\n\n" + f"/// @brief Support for {def_name} protocol\n\n" "// Supports:\n" - "// Brand: %s, Model: TODO add device and remote\n\n" + f"// Brand: {def_name}, Model: TODO add device and remote\n\n" '#include "IRrecv.h"\n' '#include "IRsend.h"\n' '#include "IRutils.h"\n\n' @@ -656,9 +655,9 @@ def generate_code(defines, code, bits_str, name="", output=sys.stdout): "// See https://github.com/crankyoldgit/IRremoteESP8266/wiki/" "Adding-support-for-a-new-IR-protocol\n" "// for details of how to include this in the library." - "\n" % (def_name, def_name)) + "\n") for line in defines: - output.write("%s\n" % line) + output.write(f"{line}\n") if len(bits_str) > 64: # Will it fit in a uint64_t? output.write("// DANGER: More than 64 bits detected. A uint64_t for " @@ -668,18 +667,21 @@ def generate_code(defines, code, bits_str, name="", output=sys.stdout): for line in code["sendcomhead"] + code["send"] + code["sendcomfoot"]: if line == SAFE64NOTE: line = "// Function should be safe up to 64 bits." - output.write("%s\n" % line) + output.write(f"{line}\n") if len(bits_str) > 64: # Will it fit in a uint64_t? for line in code["sendcomhead"] + code["send64+"] + code["sendcomfoot"]: if line == SAFE64NOTE: - line = "// Alternative >64bit function to send %s messages\n" % \ - def_name.upper() + "// Function should be safe over 64 bits." + line = (f"// Alternative >64bit function to send {def_name.upper()}" + " messages\n" + "// Function should be safe over 64 bits.") elif line == CODEGEN: + # pylint: disable=C0209 line = "/// uint8_t data[k%sStateLength] = {0x%s};" % ( name, ", 0x".join("%02X" % int(bits_str[i:i + 8], 2) for i in range(0, len(bits_str), 8))) - output.write("%s\n" % line) + # pylint: enable=C0209 + output.write(f"{line}\n") if len(bits_str) > 64: # Will it fit in a uint64_t? output.write("\n// DANGER: More than 64 bits detected. A uint64_t for " "'data' won't work!") @@ -689,7 +691,7 @@ def generate_code(defines, code, bits_str, name="", output=sys.stdout): for line in code["recvcomhead"] + code["recv"] + code["recvcomfoot"]: if line == SAFE64NOTE: line = "// Function should be safe up to 64 bits." - output.write("%s\n" % line) + output.write(f"{line}\n") # Display the > 64bit version's decode code if len(bits_str) > 64: # Is it too big for a uint64_t? @@ -699,7 +701,7 @@ def generate_code(defines, code, bits_str, name="", output=sys.stdout): for line in code["recvcomhead"] + code["recv64+"] + code["recvcomfoot"]: if line == SAFE64NOTE: line = "// Function should be safe over 64 bits." - output.write("%s\n" % line) + output.write(f"{line}\n") def add_rawdata_args(parser): """Add the arguments for feeding in the rawdata string(s).""" diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/generate_irtext_h.sh b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/generate_irtext_h.sh index df2baee06..b0d9855c4 100755 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/generate_irtext_h.sh +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/generate_irtext_h.sh @@ -24,12 +24,26 @@ cat >${OUTPUT} << EOF // Constant text to be shared across all object files. // This means there is only one copy of the character/string/text etc. +#ifdef ESP8266 +class __FlashStringHelper; +#define IRTEXT_CONST_PTR_CAST(PTR)\\ + reinterpret_cast(PTR) +#define IRTEXT_CONST_PTR(NAME) const __FlashStringHelper* const NAME +#else // ESP8266 +#define IRTEXT_CONST_PTR_CAST(PTR) PTR +#define IRTEXT_CONST_PTR(NAME) const char* const NAME +#endif // ESP8266 + EOF # Parse and output contents of INPUT file. sed 's/ PROGMEM//' ${INPUT} | egrep "^(const )?char" | cut -f1 -d= | sed 's/ $/;/;s/^/extern /' | sort -u >> ${OUTPUT} - +egrep '^\s{,10}IRTEXT_CONST_STRING\(' ${INPUT} | cut -f2 -d\( | cut -f1 -d, | + sed 's/^/extern IRTEXT_CONST_PTR\(/;s/$/\);/' | sort -u >> ${OUTPUT} +egrep '^\s{,10}IRTEXT_CONST_BLOB_DECL\(' ${INPUT} | + cut -f2 -d\( | cut -f1 -d\) | + sed 's/^/extern IRTEXT_CONST_PTR\(/;s/$/\);/' | sort -u >> ${OUTPUT} # Footer cat >> ${OUTPUT} << EOF diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/mkkeywords b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/mkkeywords index 84f2a46fd..e050e4964 100755 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/mkkeywords +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/mkkeywords @@ -31,7 +31,8 @@ cat << EndOfTextEndOfTextEndOfText EndOfTextEndOfTextEndOfText CLASSES=$(egrep -h "^ *((enum|class) |} [a-zA-Z0-9_]+_t;$)" src/*.h | - sed 's/^ *//;s/enum class//;s/\;$//' | cut -d' ' -f2 | sort -u) + sed 's/^ *//;s/enum class//;s/\;$//' | cut -d' ' -f2 | sort -u | + grep -v "^__") for i in ${CLASSES}; do echo -e "${i}\tKEYWORD1" done | sort -du @@ -59,13 +60,15 @@ cat << EndOfTextEndOfTextEndOfText ####################################### EndOfTextEndOfTextEndOfText -LITERALS=$(grep "^#define [A-Z]" src/*.cpp src/*.h | +LITERALS=$(grep -h "^#define [A-Z]" src/*.cpp src/*.h | while read ignore define ignore; do echo ${define}; done | sort -u | grep -v [\(\)] | grep -v ^_ | grep -v _\$ | grep -v VIRTUAL) -CONSTS=$(grep "^const " src/*.cpp src/*.h | - sed -E 's/\[.*\] =.*//;s/ =.*//;s/^.* \*?k/k/') +CONSTS=$(grep -h "^const " src/*.cpp src/*.h | + sed -E 's/\[.*\] =.*//;s/ =.*//;s/^.* \*?k/k/'; + grep -h "^IRTEXT_CONST_" src/*.cpp src/*.h | + sed -E 's/IRTEXT_CONST_\S+\(//;s/,.*//;s/\).*//') ENUMS=$(cat src/*.h | while read a b; do if [[ ${a} == "};" ]]; then ENUM=0; @@ -76,7 +79,7 @@ ENUMS=$(cat src/*.h | while read a b; do if [[ ${a} == "enum" ]]; then ENUM=1; fi; - done) + done | grep -v "^//") for i in ${LITERALS} ${CONSTS} ${ENUMS}; do echo -e "${i}\tLITERAL1" done | sort -u diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/raw_to_pronto_code.py b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/raw_to_pronto_code.py index 307ae7121..8d8fc815c 100755 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/raw_to_pronto_code.py +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/raw_to_pronto_code.py @@ -1,4 +1,4 @@ -#!/usr/bin/python + #!/usr/bin/python """Convert IRremoteESP8266's Raw data output into Pronto Code.""" # # Copyright 2020 David Conran @@ -16,7 +16,7 @@ def parse_and_report(rawdata_str, hertz=38000, end_usecs=100000, # Parse the input. rawdata = convert_rawdata(rawdata_str) if verbose: - output.write("Found %d timing entries.\n" % len(rawdata)) + output.write(f"Found {len(rawdata)} timing entries.\n") # Do we need to pad out the rawdata to make it even in length? if end_usecs > 0 and len(rawdata) % 2 == 1: @@ -26,29 +26,29 @@ def parse_and_report(rawdata_str, hertz=38000, end_usecs=100000, # Work out the frequency code. pronto_freq = int(1000000.0 / (hertz * 0.241246)) if verbose: - output.write("Pronto frequency is %X (%d Hz).\n" % (pronto_freq, hertz)) - result.append("%04X" % pronto_freq) + output.write(f"Pronto frequency is {pronto_freq:X} ({hertz} Hz).\n") + result.append(f"{pronto_freq:04X}") period = 1000000.0 / max(1, hertz) if verbose: - output.write("Pronto period is %f uSecs.\n" % period) + output.write(f"Pronto period is {period} uSecs.\n") # Add the lengths to the code. if use_initial: - result.append("%04x" % int(len(rawdata) / 2)) # Initial burst code length - result.append("%04x" % 0) # No Repeat code length + result.append(f"{int(len(rawdata) / 2):04x}") # Initial burst code length + result.append("0000") # No Repeat code length else: - result.append("%04x" % 0) # No Initial burst code length - result.append("%04x" % int(len(rawdata) / 2)) # Repeat code length + result.append("0000") # No Initial burst code length + result.append(f"{int(len(rawdata) / 2):04x}") # Repeat code length # Add the data. if verbose: - output.write("Raw data: %s " % rawdata) + output.write(f"Raw data: {rawdata} ") for i in rawdata: - result.append("%04x" % int(i / period)) + result.append(f"{int(i / period):04x}") if generate_code: - output.write("uint16_t pronto[%d] = {0x%s};\n" % (len(result), - ", 0x".join(result))) + output.write(f"uint16_t pronto[{len(result)}] = " + f"{{0x{', 0x'.join(result)}}};\n") else: - output.write("Pronto code = '%s'\n" % " ".join(result)) + output.write(f"Pronto code = '{' '.join(result)}'\n") # pylint: enable=too-many-arguments diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/scrape_supported_devices.py b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/scrape_supported_devices.py new file mode 100755 index 000000000..f40b3e959 --- /dev/null +++ b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/scrape_supported_devices.py @@ -0,0 +1,426 @@ +#!/usr/bin/env python3 +"""Generate SupportedProtocols.md by scraping source code files""" +import pathlib +import argparse +import subprocess +from io import StringIO +import sys +import re +import time + +CODE_URL = "https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_" + +BRAND_MODEL = re.compile(r""" + Brand:\s{1,20} # "Brand:" label followd by between 1 and 20 whitespace chars. + \b(?P.{1,40})\b # The actual brand of the device, max 40 chars. + \s{0,10}, # Followed by at most 10 whitespace chars, then a comma. + \s{1,20} # The between 1 and 20 whitespace chars. + Model:\s{1,20} # "Model:" label followd by between 1 and 20 whitespace chars. + \b(?P.{1,80}) # The model info of the device, max 80 chars. + \s{0,5}$ # Followed by at most 5 whitespaces before the end of line. + """, re.VERBOSE) +ENUMS = re.compile(r"enum (\w{1,60}) {(.{1,5000}?)};", re.DOTALL) +ENUM_ENTRY = re.compile(r"^\s{1,80}(\w{1,80})", re.MULTILINE) +DECODED_PROTOCOLS = re.compile(r""" + .{0,80} # Ignore upto an 80 char line of whitespace/code etc. + # Now look for code that looks like we are assigning the Protocol type. + # There are two typical styles used: + (?:results->decode_type # The first style. + | # Or + typeguess) # The second style + \s{0,5}=\s{0,5} # The assignment operator and potential whitespace + (?:decode_type_t::)? # The protocol could have an optional type prefix. + (\w{1,40}); # Finally, the last word of code should be the Protocol. + """, re.VERBOSE) +AC_FN = re.compile(r"ir_(.{1,80})\.h") +AC_MODEL_ENUM_RE = re.compile(r"(.{1,40})_ac_remote_model_t") +IRSEND_FN_RE = re.compile(r"IRsend\.h") +ALL_FN = re.compile(r"ir_(.{1,80})\.(h|cpp)") + +EXCLUDED_PROTOCOLS = ["UNKNOWN", "UNUSED", "kLastDecodeType", "typeguess"] +EXCLUDED_ACS = ["Magiquest", "NEC"] + +def getgitcommittime(): + """Call git to get time of last commit + """ + try: + label = subprocess.check_output(\ + ["git", "show", "-s", "--format=%ct", "HEAD"]).strip() + return int(label) + except FileNotFoundError as err: + print("Git failed, which is ok, no git binary found?:", err) + return None + except subprocess.SubprocessError as err: + print("Git failed, which is ok, see output, maybe no git checkout?:", err) + return None + +def getmarkdownheader(): + """Get the generated header + """ + srctime = getgitcommittime() + # pylint: disable=C0209 + return """""".format( + time.strftime("%a %d %b %Y %H:%M:%S +0000", time.gmtime(srctime))) + # pylint: enable=C0209 + + + +def getallprotocols(): + """Return all protocls configured in IRremoteESP8266.h + """ + irremote = ARGS.directory / "IRremoteESP8266.h" + enums = getenums(irremote)["decode_type_t"] + if not enums: + errorexit("Error getting ENUMS from IRremoteESP8266.h") + return enums + + +def getdecodedprotocols(): + """All protocols that include decoding support""" + ret = set() + for path in ARGS.directory.iterdir(): + if path.suffix != ".cpp": + continue + matches = DECODED_PROTOCOLS.finditer(path.open(encoding="utf-8").read()) + for match in matches: + protocol = match.group(1) + if protocol not in EXCLUDED_PROTOCOLS: + ret.add(protocol) + return ret + + +def getallacs(): + """All supported A/C codes""" + ret = {} + for path in ARGS.directory.iterdir(): + match = AC_FN.match(path.name) + if match: + acprotocol = match.group(1) + rawmodels = getenums(path) + models = set() + for model in rawmodels: + model = model.upper() + model = model.replace(f"K{acprotocol.upper()}", "") + if model and model not in EXCLUDED_PROTOCOLS: + models.add(model) + if acprotocol in ret: + ret[acprotocol].update(models) + else: + ret[acprotocol] = models + # Parse IRsend.h's enums + match = IRSEND_FN_RE.match(path.name) + if match: + rawmodels = getenums(path) + for acprotocol, acmodels in rawmodels.items(): + models = set() + for model in acmodels: + model = model.upper() + model = model.replace(f"K{acprotocol.upper()}", "") + if model and model not in EXCLUDED_PROTOCOLS: + models.add(model) + if acprotocol in ret: + ret[acprotocol].update(models) + else: + ret[acprotocol] = models + return ret + +class FnSets(): + """Container for getalldevices""" + def __init__(self): + self.allcodes = {} + self.fnnomatch = set() + self.allhfileprotos = set() + self.fnhmatch = set() + self.fncppmatch = set() + + def add(self, supports, path): + """add the path to correct set based on supports""" + if path.suffix == ".h": + self.allhfileprotos.add(path.stem) + if supports: + if path.suffix == ".h": + self.fnhmatch.add(path.stem) + elif path.suffix == ".cpp": + self.fncppmatch.add(path.stem) + else: + self.fnnomatch.add(path.stem) + + def printwarnings(self): + """print warnings""" + # all protos with support in .cpp file, when there is a .h file + # meaning that the documentation should probably be moved to .h + # in the future, with doxygen, that might change + protosincppwithh = list(self.fncppmatch & self.allhfileprotos) + if protosincppwithh: + protosincppwithh.sort() + print("The following files has supports section in .cpp, expected in .h") + for path in protosincppwithh: + print(f"\t{path}") + + protosincppandh = list(self.fncppmatch & self.fnhmatch) + if protosincppandh: + protosincppandh.sort() + print("The following files has supports section in both .h and .cpp") + for path in protosincppandh: + print(f"\t{path}") + + nosupports = self.getnosupports() + if nosupports: + nosupports.sort() + print("The following files had no supports section:") + for path in nosupports: + print(f"\t{path}") + + return protosincppwithh or protosincppandh or nosupports + + def getnosupports(self): + """get protos without supports sections""" + return list(self.fnnomatch - self.fnhmatch - self.fncppmatch) + + +def getalldevices(): + """All devices and associated branding and model information (if available) + """ + sets = FnSets() + for path in ARGS.directory.iterdir(): + match = ALL_FN.match(path.name) + if not match: + continue + supports = extractsupports(path) + sets.add(supports, path) + protocol = match.group(1) + for brand, model in supports: + protocolbrand = (protocol, brand) + pbset = sets.allcodes.get(protocolbrand, []) + if model in pbset: + print(f"Model {model} is duplicated for {protocol}, {brand}") + sets.allcodes[protocolbrand] = pbset + [model] + + for fnprotocol in sets.getnosupports(): + sets.allcodes[(fnprotocol[3:], "Unknown")] = [] + return sets + + +def getenums(path): + """Returns the keys for the first enum type in path + """ + ret = {} + for enums in ENUMS.finditer(path.open(encoding="utf-8").read()): + if enums: + enum_name = AC_MODEL_ENUM_RE.search(enums.group(1)) + if enum_name: + enum_name = enum_name.group(1).capitalize() + else: + enum_name = enums.group(1) + ret[enum_name] = set() + for enum in ENUM_ENTRY.finditer(enums.group(2)): + enum = enum.group(1) + if enum in EXCLUDED_PROTOCOLS: + continue + ret[enum_name].add(enum) + return ret + + +ARGS = None + + +def initargs(): + """Init the command line arguments""" + global ARGS # pylint: disable=global-statement + parser = argparse.ArgumentParser() + parser.add_argument( + "-n", + "--noout", + help="generate no output data, combine with --alert to only check", + action="store_true", + ) + parser.add_argument( + "-s", + "--stdout", + help="output to stdout rather than SupportedProtocols.md", + action="store_true", + ) + parser.add_argument("-v", + "--verbose", + help="increase output verbosity", + action="store_true") + parser.add_argument( + "-a", + "--alert", + help="alert if a file does not have a supports section, " + "non zero exit code if issues where found", + action="store_true", + ) + parser.add_argument( + "directory", + nargs="?", + help="directory of the source git checkout", + default=None, + ) + ARGS = parser.parse_args() + if ARGS.directory is None: + src = pathlib.Path("../src") + if not src.is_dir(): + src = pathlib.Path("./src") + else: + src = pathlib.Path(ARGS.directory) / "src" + if not src.is_dir(): + errorexit(f"Directory not valid: {src!s}") + ARGS.directory = src + return ARGS + +def getmdfile(): + """Resolves SupportedProtocols.md path""" + foutpath = ARGS.directory / "../SupportedProtocols.md" + return foutpath.resolve() + +def errorexit(msg): + """Print an error and exit on critical error""" + sys.stderr.write(f"{msg}\n") + sys.exit(1) + +def extractsupports(path): + """Extract all of the Supports: sections and associated brands and models + """ + supports = [] + insupports = False + for line in path.open(encoding="utf-8"): + if not line.startswith("//"): + continue + line = line[2:].strip() + if line == "Supports:": + insupports = True + continue + if insupports: + match = BRAND_MODEL.match(line) + if match: + supports.append((match.group("brand"), match.group("model"))) + else: + insupports = False + continue + # search and inform about any legacy formated supports data + elif any(x in line for x in [ \ + "seems compatible with", + "be compatible with", + "it working with here"]): + print(f"\t{path.name} Legacy supports format found\n\t\t{line}") + return supports + + +def makeurl(txt, path): + """Make a Markup URL from given filename""" + return f"[{txt}]({CODE_URL + path})" + + +def outputprotocols(fout, protocols): + """For a given protocol set, sort and output the markdown""" + protocols = list(protocols) + protocols.sort() + for protocol in protocols: + fout.write(f"- {protocol}\n") + + +def generate(fout): + """Generate data to fout + return True on any issues (when alert is active)""" + decodedprotocols = getdecodedprotocols() + sendonly = getallprotocols() - decodedprotocols + allacs = getallacs() + + sets = getalldevices() + allcodes = sets.allcodes + allbrands = list(allcodes.keys()) + allbrands.sort() + + fout.write("\n# IR Protocols supported by this library\n\n") + fout.write( + "| Protocol | Brand | Model | A/C Model | Detailed A/C Support |\n") + fout.write("| --- | --- | --- | --- | --- |\n") + + for protocolbrand in allbrands: + protocol, brand = protocolbrand + codes = allcodes[protocolbrand] + codes.sort() + acmodels = [] + acsupport = "-" + if protocol in allacs: + acmodels = list(allacs[protocol]) + acmodels.sort() + brand = makeurl(brand, protocol + ".h") + if protocol not in EXCLUDED_ACS: + acsupport = "Yes" + # pylint: disable=C0209 + fout.write("| {} | **{}** | {} | {} | {} |\n".format( + makeurl(protocol, protocol + ".cpp"), + brand, + "
".join(codes).replace("|", "\\|"), + "
".join(acmodels), + acsupport, + )) + # pylint: enable=C0209 + + fout.write("\n\n## Send only protocols:\n\n") + outputprotocols(fout, sendonly) + + fout.write("\n\n## Send & decodable protocols:\n\n") + outputprotocols(fout, decodedprotocols) + + return ARGS.alert and sets.printwarnings() + +def generatenone(): + """No out write + return True on any issues""" + return generate(StringIO()) + +def generatestdout(): + """Standard out write + return True on any issues""" + fout = sys.stdout + fout.write(getmarkdownheader()) + return generate(fout) + +def generatefile(): + """File write, extra detection of changes in existing file + return True on any issues, but only if there is changes""" + # get file path + foutpath = getmdfile() + if ARGS.verbose: + print(f"Output path: {foutpath!s}") + # write data to temp memorystream + ftemp = StringIO() + ret = generate(ftemp) + # get old filedata, skipping header + with getmdfile().open("r", encoding="utf-8") as forg: + olddata = forg.readlines()[3:] + # get new data, skip first empty line + ftemp.seek(0) + newdata = ftemp.readlines()[1:] + # if new data is same as old we don't need to write anything + if newdata == olddata: + print("No changes, exit without write") + return False + # write output + with foutpath.open("w", encoding="utf-8") as fout: + fout.write(getmarkdownheader()) + fout.write(ftemp.getvalue()) + + return ret + +def main(): + """Default main function + return True on any issues""" + initargs() + if ARGS.verbose: + print(f"Looking for files in: {ARGS.directory.resolve()!s}") + if ARGS.noout: + return generatenone() + if ARGS.stdout: + return generatestdout() + # default file + return generatefile() + + +if __name__ == "__main__": + sys.exit(1 if main() else 0) diff --git a/lib/lib_basic/IRremoteESP8266/library.json b/lib/lib_basic/IRremoteESP8266/library.json index f905e1c2f..6ac0ca58a 100644 --- a/lib/lib_basic/IRremoteESP8266/library.json +++ b/lib/lib_basic/IRremoteESP8266/library.json @@ -1,6 +1,6 @@ { "name": "IRremoteESP8266", - "version": "2.7.19", + "version": "2.8.0", "keywords": "infrared, ir, remote, esp8266, esp32", "description": "Send and receive infrared signals with multiple protocols (ESP8266/ESP32)", "repository": @@ -48,8 +48,6 @@ "frameworks": "arduino", "platforms": ["espressif8266", "espressif32"], - - "build": { "srcDir": "IRremoteESP8266/src", "flags": [ "-I$PROJECT_DIR/include", "-includetasmota_options.h" ] From ca85acb687837ea25b13bc4286d56b81b69d9482 Mon Sep 17 00:00:00 2001 From: mikep1998 <44448320+mikep1998@users.noreply.github.com> Date: Fri, 19 Nov 2021 16:56:15 -0800 Subject: [PATCH 065/185] Update xdrv_54_lvgl.ino If using lvgl and universal display and NOT berry then Init_uDisplay declaration needed. --- tasmota/xdrv_54_lvgl.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasmota/xdrv_54_lvgl.ino b/tasmota/xdrv_54_lvgl.ino index c8f533310..b0987f6dd 100644 --- a/tasmota/xdrv_54_lvgl.ino +++ b/tasmota/xdrv_54_lvgl.ino @@ -363,6 +363,8 @@ extern "C" { * We use Adafruit_LvGL_Glue to leverage the Adafruit * display ecosystem. ************************************************************/ +extern Renderer *Init_uDisplay(const char *desc); + void start_lvgl(const char * uconfig); void start_lvgl(const char * uconfig) { From cad8c179b5f30c25dba6f45b87f23ff00544b2d2 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sat, 20 Nov 2021 09:49:23 +0100 Subject: [PATCH 066/185] Berry add gc objects metrics --- lib/libesp32/Berry/src/be_debuglib.c | 1 + lib/libesp32/Berry/src/be_gc.c | 9 ++++++++- lib/libesp32/Berry/src/be_gc.h | 6 +++++- lib/libesp32/Berry/src/be_vm.c | 2 ++ lib/libesp32/Berry/src/be_vm.h | 2 ++ tasmota/xdrv_52_9_berry.ino | 5 ++++- 6 files changed, 22 insertions(+), 3 deletions(-) diff --git a/lib/libesp32/Berry/src/be_debuglib.c b/lib/libesp32/Berry/src/be_debuglib.c index 13c15f50e..aa6e8df3a 100644 --- a/lib/libesp32/Berry/src/be_debuglib.c +++ b/lib/libesp32/Berry/src/be_debuglib.c @@ -169,6 +169,7 @@ static int m_counters(bvm *vm) map_insert(vm, "set", vm->counter_set); map_insert(vm, "try", vm->counter_try); map_insert(vm, "raise", vm->counter_exc); + map_insert(vm, "objects", vm->counter_gc_scanned); be_pop(vm, 1); be_return(vm); } diff --git a/lib/libesp32/Berry/src/be_gc.c b/lib/libesp32/Berry/src/be_gc.c index 0475de7b3..8fa560b73 100644 --- a/lib/libesp32/Berry/src/be_gc.c +++ b/lib/libesp32/Berry/src/be_gc.c @@ -497,6 +497,9 @@ static void delete_white(bvm *vm) prev->next = next; } free_object(vm, node); +#if BE_USE_PERF_COUNTERS + vm->counter_gc_freed++; +#endif } else { gc_setwhite(node); prev = node; @@ -537,6 +540,10 @@ void be_gc_collect(bvm *vm) if (vm->gc.status & GC_HALT) { return; /* the GC cannot run for some reason */ } +#if BE_USE_PERF_COUNTERS + vm->counter_gc_scanned = 0; + vm->counter_gc_freed = 0; +#endif #if BE_USE_OBSERVABILITY_HOOK if (vm->obshook != NULL) (*vm->obshook)(vm, BE_OBS_GC_START, vm->gc.usage); @@ -559,6 +566,6 @@ void be_gc_collect(bvm *vm) vm->gc.threshold = next_threshold(vm->gc); #if BE_USE_OBSERVABILITY_HOOK if (vm->obshook != NULL) - (*vm->obshook)(vm, BE_OBS_GC_END, vm->gc.usage); + (*vm->obshook)(vm, BE_OBS_GC_END, vm->gc.usage, vm->counter_gc_scanned, vm->counter_gc_freed); #endif } diff --git a/lib/libesp32/Berry/src/be_gc.h b/lib/libesp32/Berry/src/be_gc.h index b1b204c13..acefc3c06 100644 --- a/lib/libesp32/Berry/src/be_gc.h +++ b/lib/libesp32/Berry/src/be_gc.h @@ -37,7 +37,11 @@ if (!gc_isconst(o)) { \ #define gc_setwhite(o) gc_setmark((o), GC_WHITE) #define gc_setgray(o) gc_setmark((o), GC_GRAY) -#define gc_setdark(o) gc_setmark((o), GC_DARK) +#if BE_USE_PERF_COUNTERS + #define gc_setdark(o) { vm->counter_gc_scanned++; gc_setmark((o), GC_DARK); } +#else + #define gc_setdark(o) gc_setmark((o), GC_DARK) +#endif #define gc_isfixed(o) (((o)->marked & GC_FIXED) != 0) #define gc_setfixed(o) ((o)->marked |= GC_FIXED) #define gc_clearfixed(o) ((o)->marked &= ~GC_FIXED) diff --git a/lib/libesp32/Berry/src/be_vm.c b/lib/libesp32/Berry/src/be_vm.c index 48834910e..fabba9220 100644 --- a/lib/libesp32/Berry/src/be_vm.c +++ b/lib/libesp32/Berry/src/be_vm.c @@ -472,6 +472,8 @@ BERRY_API bvm* be_vm_new(void) vm->counter_set = 0; vm->counter_try = 0; vm->counter_exc = 0; + vm->counter_gc_scanned = 0; + vm->counter_gc_freed = 0; #endif return vm; } diff --git a/lib/libesp32/Berry/src/be_vm.h b/lib/libesp32/Berry/src/be_vm.h index 5890ecd41..0a512210b 100644 --- a/lib/libesp32/Berry/src/be_vm.h +++ b/lib/libesp32/Berry/src/be_vm.h @@ -112,6 +112,8 @@ struct bvm { uint32_t counter_set; /* counter for SETMBR */ uint32_t counter_try; /* counter for `try` statement */ uint32_t counter_exc; /* counter for raised exceptions */ + uint32_t counter_gc_scanned; /* counter for objects scanned by last gc */ + uint32_t counter_gc_freed; /* counter for objects freed by last gc */ #endif #if BE_USE_DEBUG_HOOK bvalue hook; diff --git a/tasmota/xdrv_52_9_berry.ino b/tasmota/xdrv_52_9_berry.ino index c2ed977be..ff74ba950 100644 --- a/tasmota/xdrv_52_9_berry.ino +++ b/tasmota/xdrv_52_9_berry.ino @@ -262,7 +262,10 @@ void BerryObservability(bvm *vm, int event...) { { int32_t vm_usage2 = va_arg(param, int32_t); uint32_t gc_elapsed = millis() - gc_time; - AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "GC from %i to %i bytes (in %d ms)"), vm_usage, vm_usage2, gc_elapsed); + uint32_t vm_scanned = va_arg(param, uint32_t); + uint32_t vm_freed = va_arg(param, uint32_t); + AddLog(LOG_LEVEL_DEBUG, D_LOG_BERRY "GC from %i to %i bytes, objects freed %i/%i (in %d ms)", + vm_usage, vm_usage2, vm_freed, vm_scanned, gc_elapsed); // make new threshold tighter when we reach high memory usage if (!UsePSRAM() && vm->gc.threshold > 20*1024) { vm->gc.threshold = vm->gc.usage + 10*1024; // increase by only 10 KB From 56f5584a46007bd03d1c8ae690c418df1275e995 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sat, 20 Nov 2021 11:29:04 +0100 Subject: [PATCH 067/185] Berry allow import in tapp (#13743) * Berry allow import in tapp * Avoid patching Berry --- lib/libesp32/Berry/default/berry_conf.h | 2 +- lib/libesp32/Berry/generate/be_const_strtab.h | 681 ++++++------ .../Berry/generate/be_const_strtab_def.h | 990 +++++++++--------- lib/libesp32/Berry/generate/be_fixed_sys.h | 15 + .../Zip-readonly-FS/src/ZipReadFS.cpp | 2 + 5 files changed, 855 insertions(+), 835 deletions(-) diff --git a/lib/libesp32/Berry/default/berry_conf.h b/lib/libesp32/Berry/default/berry_conf.h index 597c3d65b..d2284ac31 100644 --- a/lib/libesp32/Berry/default/berry_conf.h +++ b/lib/libesp32/Berry/default/berry_conf.h @@ -193,7 +193,7 @@ #define BE_USE_TIME_MODULE 0 #define BE_USE_OS_MODULE 0 #define BE_USE_GLOBAL_MODULE 1 -#define BE_USE_SYS_MODULE 0 +#define BE_USE_SYS_MODULE 1 #define BE_USE_DEBUG_MODULE 0 #define BE_USE_GC_MODULE 1 #define BE_USE_SOLIDIFY_MODULE 0 diff --git a/lib/libesp32/Berry/generate/be_const_strtab.h b/lib/libesp32/Berry/generate/be_const_strtab.h index 718eac65c..12a0ebefc 100644 --- a/lib/libesp32/Berry/generate/be_const_strtab.h +++ b/lib/libesp32/Berry/generate/be_const_strtab.h @@ -1,347 +1,348 @@ -extern const bcstring be_const_str_setmember; -extern const bcstring be_const_str_hex; -extern const bcstring be_const_str_arch; -extern const bcstring be_const_str_resolvecmnd; -extern const bcstring be_const_str_resp_cmnd_done; -extern const bcstring be_const_str_top; -extern const bcstring be_const_str_content_start; -extern const bcstring be_const_str_deg; -extern const bcstring be_const_str_fromptr; -extern const bcstring be_const_str_time_dump; -extern const bcstring be_const_str_compile; -extern const bcstring be_const_str_members; -extern const bcstring be_const_str_arg_name; -extern const bcstring be_const_str_real; -extern const bcstring be_const_str_insert; -extern const bcstring be_const_str_open; -extern const bcstring be_const_str_ctypes_bytes; -extern const bcstring be_const_str_tag; -extern const bcstring be_const_str_reset; -extern const bcstring be_const_str_toupper; -extern const bcstring be_const_str_POST; -extern const bcstring be_const_str_SERIAL_6O2; -extern const bcstring be_const_str_iter; -extern const bcstring be_const_str_load; -extern const bcstring be_const_str_available; -extern const bcstring be_const_str_ceil; -extern const bcstring be_const_str_clear; -extern const bcstring be_const_str_digital_read; -extern const bcstring be_const_str__get_cb; -extern const bcstring be_const_str_bytes; -extern const bcstring be_const_str_settings; -extern const bcstring be_const_str_get_string; -extern const bcstring be_const_str_asstring; -extern const bcstring be_const_str_pin_used; -extern const bcstring be_const_str_pop; -extern const bcstring be_const_str_static; -extern const bcstring be_const_str_AES_GCM; -extern const bcstring be_const_str_SERIAL_8N2; -extern const bcstring be_const_str_close; -extern const bcstring be_const_str_set_power; -extern const bcstring be_const_str_find_op; -extern const bcstring be_const_str_get; -extern const bcstring be_const_str_print; -extern const bcstring be_const_str_publish_result; -extern const bcstring be_const_str_target_search; -extern const bcstring be_const_str__ccmd; -extern const bcstring be_const_str_fromb64; -extern const bcstring be_const_str_module; -extern const bcstring be_const_str_allocated; -extern const bcstring be_const_str_GET; -extern const bcstring be_const_str_SERIAL_8E1; -extern const bcstring be_const_str_classof; -extern const bcstring be_const_str_cos; -extern const bcstring be_const_str_assert; -extern const bcstring be_const_str_content_send; -extern const bcstring be_const_str_read13; -extern const bcstring be_const_str_reverse; -extern const bcstring be_const_str_set_timer; -extern const bcstring be_const_str_class; -extern const bcstring be_const_str_codedump; -extern const bcstring be_const_str_isrunning; -extern const bcstring be_const_str_publish; -extern const bcstring be_const_str_range; -extern const bcstring be_const_str_write; -extern const bcstring be_const_str_opt_connect; -extern const bcstring be_const_str_SERIAL_7O1; -extern const bcstring be_const_str_update; -extern const bcstring be_const_str__cmd; -extern const bcstring be_const_str_isnan; -extern const bcstring be_const_str_resp_cmnd_failed; -extern const bcstring be_const_str_SERIAL_5O1; -extern const bcstring be_const_str_abs; -extern const bcstring be_const_str_SERIAL_7E2; -extern const bcstring be_const_str_SERIAL_6N1; -extern const bcstring be_const_str__cb; -extern const bcstring be_const_str_depower; -extern const bcstring be_const_str_Tasmota; -extern const bcstring be_const_str_item; -extern const bcstring be_const_str_set_useragent; -extern const bcstring be_const_str_wire2; -extern const bcstring be_const_str_time_reached; -extern const bcstring be_const_str_chars_in_string; -extern const bcstring be_const_str_false; -extern const bcstring be_const_str_add_rule; -extern const bcstring be_const_str_setbits; -extern const bcstring be_const_str_write_file; -extern const bcstring be_const_str_hs2rgb; -extern const bcstring be_const_str_SERIAL_8O1; -extern const bcstring be_const_str_wd; -extern const bcstring be_const_str_wire_scan; -extern const bcstring be_const_str_AudioFileSourceFS; -extern const bcstring be_const_str_get_free_heap; -extern const bcstring be_const_str_AudioGenerator; -extern const bcstring be_const_str_SERIAL_5E2; -extern const bcstring be_const_str__global_addr; -extern const bcstring be_const_str_content_send_style; -extern const bcstring be_const_str_remove_timer; -extern const bcstring be_const_str_tr; -extern const bcstring be_const_str_dot_w; -extern const bcstring be_const_str_MD5; -extern const bcstring be_const_str_break; -extern const bcstring be_const_str_digital_write; -extern const bcstring be_const_str_asin; -extern const bcstring be_const_str__def; -extern const bcstring be_const_str_exec_cmd; -extern const bcstring be_const_str_exists; -extern const bcstring be_const_str_flush; -extern const bcstring be_const_str_as; -extern const bcstring be_const_str_set_light; -extern const bcstring be_const_str_time_str; -extern const bcstring be_const_str_arg_size; -extern const bcstring be_const_str_bus; -extern const bcstring be_const_str_opt_eq; -extern const bcstring be_const_str_try_rule; -extern const bcstring be_const_str_kv; -extern const bcstring be_const_str_reverse_gamma10; -extern const bcstring be_const_str_tostring; -extern const bcstring be_const_str_format; -extern const bcstring be_const_str_tob64; -extern const bcstring be_const_str_continue; -extern const bcstring be_const_str_log; -extern const bcstring be_const_str_SERIAL_7N1; -extern const bcstring be_const_str_lower; -extern const bcstring be_const_str_stop; -extern const bcstring be_const_str_count; -extern const bcstring be_const_str_encrypt; -extern const bcstring be_const_str_resp_cmnd_str; -extern const bcstring be_const_str_byte; -extern const bcstring be_const_str_fromstring; -extern const bcstring be_const_str_run_deferred; -extern const bcstring be_const_str_setitem; -extern const bcstring be_const_str_cmd; -extern const bcstring be_const_str_event; -extern const bcstring be_const_str_SERIAL_6E1; -extern const bcstring be_const_str_SERIAL_6O1; -extern const bcstring be_const_str_remove_driver; -extern const bcstring be_const_str_EC_C25519; -extern const bcstring be_const_str_read12; -extern const bcstring be_const_str__write; -extern const bcstring be_const_str_opt_call; -extern const bcstring be_const_str_AudioOutput; -extern const bcstring be_const_str_attrdump; -extern const bcstring be_const_str_int; -extern const bcstring be_const_str_AudioGeneratorMP3; -extern const bcstring be_const_str_add_header; -extern const bcstring be_const_str_ctypes_bytes_dyn; -extern const bcstring be_const_str_keys; -extern const bcstring be_const_str_set_auth; -extern const bcstring be_const_str_def; -extern const bcstring be_const_str_; -extern const bcstring be_const_str_SERIAL_5N2; -extern const bcstring be_const_str__rules; -extern const bcstring be_const_str_has; -extern const bcstring be_const_str_set; -extern const bcstring be_const_str_public_key; -extern const bcstring be_const_str_get_power; -extern const bcstring be_const_str_type; -extern const bcstring be_const_str_opt_add; -extern const bcstring be_const_str_dot_size; -extern const bcstring be_const_str_set_timeouts; -extern const bcstring be_const_str_tomap; -extern const bcstring be_const_str_getbits; -extern const bcstring be_const_str_sinh; -extern const bcstring be_const_str_sqrt; -extern const bcstring be_const_str_dot_p1; -extern const bcstring be_const_str_begin; -extern const bcstring be_const_str_delay; -extern const bcstring be_const_str_scan; -extern const bcstring be_const_str_for; -extern const bcstring be_const_str_read8; -extern const bcstring be_const_str_AudioGeneratorWAV; -extern const bcstring be_const_str_get_light; -extern const bcstring be_const_str__global_def; -extern const bcstring be_const_str_map; -extern const bcstring be_const_str_redirect; -extern const bcstring be_const_str__ptr; -extern const bcstring be_const_str_isinstance; -extern const bcstring be_const_str_pin; -extern const bcstring be_const_str_size; -extern const bcstring be_const_str_state; -extern const bcstring be_const_str_dot_p; -extern const bcstring be_const_str__drivers; -extern const bcstring be_const_str_erase; -extern const bcstring be_const_str_I2C_Driver; -extern const bcstring be_const_str_addr; -extern const bcstring be_const_str_copy; -extern const bcstring be_const_str_find_key_i; -extern const bcstring be_const_str_pin_mode; -extern const bcstring be_const_str_setrange; -extern const bcstring be_const_str_SERIAL_8N1; -extern const bcstring be_const_str_char; -extern const bcstring be_const_str_concat; +extern const bcstring be_const_str_pow; extern const bcstring be_const_str_remove; -extern const bcstring be_const_str_serial; -extern const bcstring be_const_str_SERIAL_5O2; -extern const bcstring be_const_str__read; -extern const bcstring be_const_str_cmd_res; -extern const bcstring be_const_str_contains; -extern const bcstring be_const_str_imax; -extern const bcstring be_const_str_super; -extern const bcstring be_const_str_try; -extern const bcstring be_const_str_last_modified; -extern const bcstring be_const_str_return; -extern const bcstring be_const_str_SERIAL_6N2; -extern const bcstring be_const_str_call; -extern const bcstring be_const_str_resize; -extern const bcstring be_const_str_escape; -extern const bcstring be_const_str_upper; -extern const bcstring be_const_str_end; -extern const bcstring be_const_str_gamma8; -extern const bcstring be_const_str_memory; -extern const bcstring be_const_str_wifi; -extern const bcstring be_const_str_yield; -extern const bcstring be_const_str_get_option; -extern const bcstring be_const_str_init; -extern const bcstring be_const_str_read; -extern const bcstring be_const_str__settings_ptr; -extern const bcstring be_const_str__timers; -extern const bcstring be_const_str_finish; -extern const bcstring be_const_str___upper__; -extern const bcstring be_const_str_dump; -extern const bcstring be_const_str_save; -extern const bcstring be_const_str___lower__; -extern const bcstring be_const_str_listdir; -extern const bcstring be_const_str_check_privileged_access; -extern const bcstring be_const_str_rand; -extern const bcstring be_const_str_web_send; -extern const bcstring be_const_str_i2c_enabled; -extern const bcstring be_const_str_wire1; -extern const bcstring be_const_str_dac_voltage; -extern const bcstring be_const_str_imin; -extern const bcstring be_const_str_log10; -extern const bcstring be_const_str_skip; -extern const bcstring be_const_str_else; -extern const bcstring be_const_str_except; -extern const bcstring be_const_str_nil; -extern const bcstring be_const_str_resp_cmnd_error; -extern const bcstring be_const_str_calldepth; -extern const bcstring be_const_str_do; -extern const bcstring be_const_str___iterator__; -extern const bcstring be_const_str_true; -extern const bcstring be_const_str_rad; +extern const bcstring be_const_str_remove_timer; +extern const bcstring be_const_str_MD5; +extern const bcstring be_const_str__ccmd; +extern const bcstring be_const_str_digital_write; +extern const bcstring be_const_str_dot_p2; +extern const bcstring be_const_str_floor; +extern const bcstring be_const_str_input; +extern const bcstring be_const_str_range; +extern const bcstring be_const_str_atan; +extern const bcstring be_const_str_find_op; +extern const bcstring be_const_str_SERIAL_6N1; +extern const bcstring be_const_str_classname; +extern const bcstring be_const_str_content_start; extern const bcstring be_const_str_import; -extern const bcstring be_const_str_SERIAL_8O2; -extern const bcstring be_const_str_gamma10; -extern const bcstring be_const_str_elif; -extern const bcstring be_const_str_resp_cmnd; -extern const bcstring be_const_str_shared_key; -extern const bcstring be_const_str_web_send_decimal; -extern const bcstring be_const_str_write8; -extern const bcstring be_const_str_SERIAL_5E1; -extern const bcstring be_const_str_member; -extern const bcstring be_const_str_sin; -extern const bcstring be_const_str_OneWire; -extern const bcstring be_const_str_SERIAL_7O2; +extern const bcstring be_const_str_raise; +extern const bcstring be_const_str_SERIAL_8N2; +extern const bcstring be_const_str_keys; +extern const bcstring be_const_str_content_send_style; +extern const bcstring be_const_str_static; extern const bcstring be_const_str__begin_transmission; -extern const bcstring be_const_str_get_switch; -extern const bcstring be_const_str_name; -extern const bcstring be_const_str_nan; +extern const bcstring be_const_str__request_from; +extern const bcstring be_const_str_isnan; +extern const bcstring be_const_str_reverse_gamma10; +extern const bcstring be_const_str_number; +extern const bcstring be_const_str_resp_cmnd_str; +extern const bcstring be_const_str_run_deferred; +extern const bcstring be_const_str_exec_rules; +extern const bcstring be_const_str_web_send; +extern const bcstring be_const_str_GET; +extern const bcstring be_const_str__rules; +extern const bcstring be_const_str_begin; +extern const bcstring be_const_str_escape; +extern const bcstring be_const_str_I2C_Driver; +extern const bcstring be_const_str_char; +extern const bcstring be_const_str_opt_neq; +extern const bcstring be_const_str_Wire; +extern const bcstring be_const_str_asstring; +extern const bcstring be_const_str_strftime; +extern const bcstring be_const_str_last_modified; +extern const bcstring be_const_str_set; extern const bcstring be_const_str_add; extern const bcstring be_const_str_eth; -extern const bcstring be_const_str_find; -extern const bcstring be_const_str_read32; -extern const bcstring be_const_str_remove_cmd; -extern const bcstring be_const_str_gc; -extern const bcstring be_const_str_reset_search; -extern const bcstring be_const_str_content_stop; -extern const bcstring be_const_str_counters; -extern const bcstring be_const_str_detect; -extern const bcstring be_const_str_exp; -extern const bcstring be_const_str_on; -extern const bcstring be_const_str_arg; -extern const bcstring be_const_str_reduce; -extern const bcstring be_const_str_split; -extern const bcstring be_const_str_strftime; -extern const bcstring be_const_str_raise; -extern const bcstring be_const_str_AudioOutputI2S; -extern const bcstring be_const_str_if; -extern const bcstring be_const_str_cb_dispatch; -extern const bcstring be_const_str_exec_tele; -extern const bcstring be_const_str_srand; -extern const bcstring be_const_str_write_bytes; -extern const bcstring be_const_str__settings_def; -extern const bcstring be_const_str_cosh; -extern const bcstring be_const_str_pi; -extern const bcstring be_const_str_remove_rule; -extern const bcstring be_const_str_scale_uint; -extern const bcstring be_const_str_var; -extern const bcstring be_const_str_SERIAL_8E2; -extern const bcstring be_const_str_acos; -extern const bcstring be_const_str_gen_cb; -extern const bcstring be_const_str_read_bytes; -extern const bcstring be_const_str_AudioFileSource; -extern const bcstring be_const_str_SERIAL_5N1; -extern const bcstring be_const_str_wire; -extern const bcstring be_const_str_while; -extern const bcstring be_const_str_SERIAL_7N2; -extern const bcstring be_const_str_get_size; -extern const bcstring be_const_str_exec_rules; -extern const bcstring be_const_str__available; -extern const bcstring be_const_str_search; -extern const bcstring be_const_str_global; -extern const bcstring be_const_str_collect; -extern const bcstring be_const_str_input; -extern const bcstring be_const_str_response_append; -extern const bcstring be_const_str_str; -extern const bcstring be_const_str_SERIAL_6E2; -extern const bcstring be_const_str_SERIAL_7E1; -extern const bcstring be_const_str_content_button; -extern const bcstring be_const_str_number; -extern const bcstring be_const_str_tanh; -extern const bcstring be_const_str_toptr; -extern const bcstring be_const_str_write_bit; -extern const bcstring be_const_str_add_cmd; -extern const bcstring be_const_str_select; -extern const bcstring be_const_str_traceback; -extern const bcstring be_const_str_atan2; -extern const bcstring be_const_str_loop; -extern const bcstring be_const_str_millis; -extern const bcstring be_const_str_url_encode; -extern const bcstring be_const_str__end_transmission; -extern const bcstring be_const_str_deinit; -extern const bcstring be_const_str_tan; -extern const bcstring be_const_str_geti; -extern const bcstring be_const_str_seti; -extern const bcstring be_const_str__buffer; -extern const bcstring be_const_str_atan; -extern const bcstring be_const_str_content_flush; -extern const bcstring be_const_str_list; -extern const bcstring be_const_str_tolower; -extern const bcstring be_const_str_dot_len; -extern const bcstring be_const_str__request_from; -extern const bcstring be_const_str_has_arg; -extern const bcstring be_const_str_pow; -extern const bcstring be_const_str_push; -extern const bcstring be_const_str_read24; -extern const bcstring be_const_str_enabled; -extern const bcstring be_const_str_webclient; -extern const bcstring be_const_str_opt_neq; -extern const bcstring be_const_str_dot_p2; -extern const bcstring be_const_str_Wire; -extern const bcstring be_const_str_decrypt; -extern const bcstring be_const_str_floor; -extern const bcstring be_const_str_issubclass; -extern const bcstring be_const_str_classname; +extern const bcstring be_const_str_publish; extern const bcstring be_const_str_rtc; +extern const bcstring be_const_str_scan; +extern const bcstring be_const_str_EC_C25519; +extern const bcstring be_const_str_nil; +extern const bcstring be_const_str_ceil; +extern const bcstring be_const_str_item; +extern const bcstring be_const_str_log; +extern const bcstring be_const_str__global_def; +extern const bcstring be_const_str_clear; +extern const bcstring be_const_str_atan2; +extern const bcstring be_const_str_dump; +extern const bcstring be_const_str_fromb64; +extern const bcstring be_const_str_deinit; +extern const bcstring be_const_str_read13; +extern const bcstring be_const_str_SERIAL_8O1; +extern const bcstring be_const_str_SERIAL_6O1; +extern const bcstring be_const_str_add_rule; +extern const bcstring be_const_str_fromstring; +extern const bcstring be_const_str_SERIAL_6E2; +extern const bcstring be_const_str_try_rule; +extern const bcstring be_const_str_gc; +extern const bcstring be_const_str_publish_result; +extern const bcstring be_const_str_response_append; +extern const bcstring be_const_str_continue; +extern const bcstring be_const_str_dot_p1; +extern const bcstring be_const_str__def; +extern const bcstring be_const_str_imin; +extern const bcstring be_const_str_chars_in_string; +extern const bcstring be_const_str_concat; +extern const bcstring be_const_str_content_stop; +extern const bcstring be_const_str_def; +extern const bcstring be_const_str_traceback; +extern const bcstring be_const_str_wire; +extern const bcstring be_const_str_calldepth; +extern const bcstring be_const_str_finish; +extern const bcstring be_const_str_log10; +extern const bcstring be_const_str_name; +extern const bcstring be_const_str_time_str; +extern const bcstring be_const_str_do; +extern const bcstring be_const_str_read; +extern const bcstring be_const_str_set_auth; +extern const bcstring be_const_str_Tasmota; +extern const bcstring be_const_str_SERIAL_7E2; +extern const bcstring be_const_str_resolvecmnd; +extern const bcstring be_const_str___lower__; +extern const bcstring be_const_str_addr; +extern const bcstring be_const_str_gamma8; +extern const bcstring be_const_str_member; +extern const bcstring be_const_str_scale_uint; +extern const bcstring be_const_str_codedump; +extern const bcstring be_const_str_opt_call; +extern const bcstring be_const_str_SERIAL_5N2; +extern const bcstring be_const_str_attrdump; +extern const bcstring be_const_str_hex; +extern const bcstring be_const_str_remove_cmd; +extern const bcstring be_const_str_AudioOutput; +extern const bcstring be_const_str_break; +extern const bcstring be_const_str_SERIAL_5O1; +extern const bcstring be_const_str_rand; +extern const bcstring be_const_str_class; +extern const bcstring be_const_str_public_key; +extern const bcstring be_const_str_search; +extern const bcstring be_const_str_update; +extern const bcstring be_const_str_end; +extern const bcstring be_const_str_i2c_enabled; +extern const bcstring be_const_str_read_bytes; +extern const bcstring be_const_str_fromptr; +extern const bcstring be_const_str_pin_used; +extern const bcstring be_const_str_redirect; +extern const bcstring be_const_str__drivers; +extern const bcstring be_const_str_get_size; +extern const bcstring be_const_str_set_power; +extern const bcstring be_const_str_loop; +extern const bcstring be_const_str_read32; +extern const bcstring be_const_str_add_cmd; +extern const bcstring be_const_str__settings_ptr; +extern const bcstring be_const_str_reset; +extern const bcstring be_const_str__ptr; +extern const bcstring be_const_str_detect; +extern const bcstring be_const_str_reset_search; +extern const bcstring be_const_str_SERIAL_6E1; +extern const bcstring be_const_str__read; +extern const bcstring be_const_str_true; +extern const bcstring be_const_str_opt_eq; extern const bcstring be_const_str_add_driver; +extern const bcstring be_const_str_tob64; +extern const bcstring be_const_str_wire1; +extern const bcstring be_const_str__timers; +extern const bcstring be_const_str_opt_connect; +extern const bcstring be_const_str_SERIAL_5E1; +extern const bcstring be_const_str_select; +extern const bcstring be_const_str_setbits; +extern const bcstring be_const_str_webclient; +extern const bcstring be_const_str_deg; +extern const bcstring be_const_str_flush; +extern const bcstring be_const_str_hs2rgb; +extern const bcstring be_const_str_SERIAL_8E1; +extern const bcstring be_const_str_setrange; +extern const bcstring be_const_str_dot_len; +extern const bcstring be_const_str_byte; +extern const bcstring be_const_str_issubclass; +extern const bcstring be_const_str_while; +extern const bcstring be_const_str_enabled; +extern const bcstring be_const_str_sin; +extern const bcstring be_const_str_except; +extern const bcstring be_const_str_AudioOutputI2S; +extern const bcstring be_const_str_SERIAL_7N2; +extern const bcstring be_const_str_call; +extern const bcstring be_const_str_imax; +extern const bcstring be_const_str_isrunning; +extern const bcstring be_const_str_read8; +extern const bcstring be_const_str_resp_cmnd_error; +extern const bcstring be_const_str_AudioFileSourceFS; +extern const bcstring be_const_str___iterator__; +extern const bcstring be_const_str_contains; +extern const bcstring be_const_str_web_send_decimal; +extern const bcstring be_const_str_dac_voltage; +extern const bcstring be_const_str_time_reached; +extern const bcstring be_const_str_if; +extern const bcstring be_const_str_read24; +extern const bcstring be_const_str_toptr; +extern const bcstring be_const_str_else; +extern const bcstring be_const_str__global_addr; +extern const bcstring be_const_str_classof; +extern const bcstring be_const_str_SERIAL_7O1; +extern const bcstring be_const_str_print; +extern const bcstring be_const_str_setmember; +extern const bcstring be_const_str_dot_size; +extern const bcstring be_const_str__write; +extern const bcstring be_const_str_init; +extern const bcstring be_const_str_gamma10; +extern const bcstring be_const_str_gen_cb; +extern const bcstring be_const_str_remove_rule; +extern const bcstring be_const_str_ctypes_bytes_dyn; +extern const bcstring be_const_str_SERIAL_6N2; +extern const bcstring be_const_str_available; +extern const bcstring be_const_str_cb_dispatch; +extern const bcstring be_const_str_isinstance; +extern const bcstring be_const_str_copy; +extern const bcstring be_const_str_find; +extern const bcstring be_const_str_POST; +extern const bcstring be_const_str_write_bytes; +extern const bcstring be_const_str_; +extern const bcstring be_const_str_type; +extern const bcstring be_const_str_allocated; +extern const bcstring be_const_str_insert; +extern const bcstring be_const_str_tolower; +extern const bcstring be_const_str_dot_w; +extern const bcstring be_const_str_srand; +extern const bcstring be_const_str_wire2; +extern const bcstring be_const_str_format; +extern const bcstring be_const_str_yield; +extern const bcstring be_const_str_SERIAL_5E2; +extern const bcstring be_const_str_reduce; +extern const bcstring be_const_str_resp_cmnd_done; +extern const bcstring be_const_str_abs; +extern const bcstring be_const_str_setitem; +extern const bcstring be_const_str_OneWire; +extern const bcstring be_const_str_upper; +extern const bcstring be_const_str_module; +extern const bcstring be_const_str_counters; +extern const bcstring be_const_str_tag; +extern const bcstring be_const_str_tanh; +extern const bcstring be_const_str_get_string; +extern const bcstring be_const_str_read12; +extern const bcstring be_const_str_wire_scan; +extern const bcstring be_const_str_seti; +extern const bcstring be_const_str_cmd; +extern const bcstring be_const_str_content_send; +extern const bcstring be_const_str_global; +extern const bcstring be_const_str_var; +extern const bcstring be_const_str_SERIAL_7N1; +extern const bcstring be_const_str_resize; +extern const bcstring be_const_str_split; +extern const bcstring be_const_str_str; +extern const bcstring be_const_str_url_encode; +extern const bcstring be_const_str_get_option; +extern const bcstring be_const_str_listdir; +extern const bcstring be_const_str_tomap; +extern const bcstring be_const_str_check_privileged_access; +extern const bcstring be_const_str_pin_mode; +extern const bcstring be_const_str_pin; +extern const bcstring be_const_str_try; +extern const bcstring be_const_str__buffer; +extern const bcstring be_const_str_cos; +extern const bcstring be_const_str_dot_p; +extern const bcstring be_const_str_SERIAL_7O2; +extern const bcstring be_const_str_real; +extern const bcstring be_const_str_set_timer; +extern const bcstring be_const_str_count; +extern const bcstring be_const_str_write; +extern const bcstring be_const_str__settings_def; +extern const bcstring be_const_str_digital_read; +extern const bcstring be_const_str_path; +extern const bcstring be_const_str_delay; +extern const bcstring be_const_str_stop; +extern const bcstring be_const_str_AES_GCM; +extern const bcstring be_const_str_SERIAL_6O2; +extern const bcstring be_const_str_open; +extern const bcstring be_const_str_top; +extern const bcstring be_const_str_write_bit; +extern const bcstring be_const_str_state; +extern const bcstring be_const_str_set_useragent; +extern const bcstring be_const_str_as; +extern const bcstring be_const_str_erase; +extern const bcstring be_const_str_has_arg; +extern const bcstring be_const_str_map; +extern const bcstring be_const_str_on; +extern const bcstring be_const_str_AudioGeneratorWAV; +extern const bcstring be_const_str__cb; +extern const bcstring be_const_str_decrypt; +extern const bcstring be_const_str_sqrt; +extern const bcstring be_const_str_SERIAL_5N1; +extern const bcstring be_const_str_find_key_i; +extern const bcstring be_const_str_arg; +extern const bcstring be_const_str_depower; +extern const bcstring be_const_str_write_file; +extern const bcstring be_const_str_SERIAL_5O2; +extern const bcstring be_const_str_get_light; +extern const bcstring be_const_str_pop; +extern const bcstring be_const_str_exec_tele; +extern const bcstring be_const_str_set_light; +extern const bcstring be_const_str_set_timeouts; +extern const bcstring be_const_str_sinh; +extern const bcstring be_const_str_AudioGenerator; +extern const bcstring be_const_str_SERIAL_7E1; +extern const bcstring be_const_str_getbits; +extern const bcstring be_const_str_shared_key; +extern const bcstring be_const_str_time_dump; +extern const bcstring be_const_str_content_button; +extern const bcstring be_const_str_geti; +extern const bcstring be_const_str_arch; +extern const bcstring be_const_str_asin; +extern const bcstring be_const_str_get_free_heap; +extern const bcstring be_const_str_resp_cmnd; +extern const bcstring be_const_str_content_flush; +extern const bcstring be_const_str_millis; +extern const bcstring be_const_str_serial; +extern const bcstring be_const_str_skip; +extern const bcstring be_const_str_event; +extern const bcstring be_const_str_opt_add; +extern const bcstring be_const_str_bus; +extern const bcstring be_const_str_acos; +extern const bcstring be_const_str_bytes; +extern const bcstring be_const_str_compile; +extern const bcstring be_const_str_get; +extern const bcstring be_const_str_tan; +extern const bcstring be_const_str_encrypt; +extern const bcstring be_const_str_cmd_res; +extern const bcstring be_const_str_collect; +extern const bcstring be_const_str_arg_size; +extern const bcstring be_const_str_reverse; +extern const bcstring be_const_str_close; +extern const bcstring be_const_str_members; +extern const bcstring be_const_str_assert; +extern const bcstring be_const_str_exec_cmd; +extern const bcstring be_const_str_get_power; +extern const bcstring be_const_str_resp_cmnd_failed; +extern const bcstring be_const_str_target_search; +extern const bcstring be_const_str_AudioFileSource; +extern const bcstring be_const_str_SERIAL_8N1; +extern const bcstring be_const_str_pi; +extern const bcstring be_const_str_add_header; +extern const bcstring be_const_str_list; +extern const bcstring be_const_str_super; +extern const bcstring be_const_str_has; +extern const bcstring be_const_str___upper__; +extern const bcstring be_const_str_exp; +extern const bcstring be_const_str_int; +extern const bcstring be_const_str_size; +extern const bcstring be_const_str_for; +extern const bcstring be_const_str_ctypes_bytes; +extern const bcstring be_const_str_wifi; +extern const bcstring be_const_str_elif; +extern const bcstring be_const_str_arg_name; +extern const bcstring be_const_str_cosh; +extern const bcstring be_const_str_lower; +extern const bcstring be_const_str_push; +extern const bcstring be_const_str_save; +extern const bcstring be_const_str_load; +extern const bcstring be_const_str_SERIAL_8E2; +extern const bcstring be_const_str_nan; +extern const bcstring be_const_str_remove_driver; +extern const bcstring be_const_str_write8; +extern const bcstring be_const_str__get_cb; +extern const bcstring be_const_str_iter; +extern const bcstring be_const_str__cmd; +extern const bcstring be_const_str_exists; +extern const bcstring be_const_str_AudioGeneratorMP3; +extern const bcstring be_const_str__end_transmission; +extern const bcstring be_const_str_get_switch; +extern const bcstring be_const_str__available; +extern const bcstring be_const_str_false; +extern const bcstring be_const_str_settings; +extern const bcstring be_const_str_wd; +extern const bcstring be_const_str_SERIAL_8O2; +extern const bcstring be_const_str_rad; +extern const bcstring be_const_str_kv; +extern const bcstring be_const_str_toupper; +extern const bcstring be_const_str_tr; +extern const bcstring be_const_str_return; +extern const bcstring be_const_str_memory; +extern const bcstring be_const_str_tostring; diff --git a/lib/libesp32/Berry/generate/be_const_strtab_def.h b/lib/libesp32/Berry/generate/be_const_strtab_def.h index aed550fdc..759cf6c02 100644 --- a/lib/libesp32/Berry/generate/be_const_strtab_def.h +++ b/lib/libesp32/Berry/generate/be_const_strtab_def.h @@ -1,518 +1,520 @@ -be_define_const_str(setmember, "setmember", 1432909441u, 0, 9, NULL); -be_define_const_str(hex, "hex", 4273249610u, 0, 3, NULL); -be_define_const_str(arch, "arch", 2952804297u, 0, 4, &be_const_str_resolvecmnd); -be_define_const_str(resolvecmnd, "resolvecmnd", 993361485u, 0, 11, &be_const_str_resp_cmnd_done); -be_define_const_str(resp_cmnd_done, "resp_cmnd_done", 2601874875u, 0, 14, NULL); -be_define_const_str(top, "top", 2802900028u, 0, 3, NULL); -be_define_const_str(content_start, "content_start", 2937509069u, 0, 13, &be_const_str_deg); -be_define_const_str(deg, "deg", 3327754271u, 0, 3, &be_const_str_fromptr); -be_define_const_str(fromptr, "fromptr", 666189689u, 0, 7, &be_const_str_time_dump); -be_define_const_str(time_dump, "time_dump", 3330410747u, 0, 9, NULL); -be_define_const_str(compile, "compile", 1000265118u, 0, 7, &be_const_str_members); -be_define_const_str(members, "members", 937576464u, 0, 7, NULL); -be_define_const_str(arg_name, "arg_name", 1345046155u, 0, 8, &be_const_str_real); -be_define_const_str(real, "real", 3604983901u, 0, 4, NULL); -be_define_const_str(insert, "insert", 3332609576u, 0, 6, NULL); -be_define_const_str(open, "open", 3546203337u, 0, 4, NULL); -be_define_const_str(ctypes_bytes, "ctypes_bytes", 3879019703u, 0, 12, &be_const_str_tag); -be_define_const_str(tag, "tag", 2516003219u, 0, 3, NULL); -be_define_const_str(reset, "reset", 1695364032u, 0, 5, &be_const_str_toupper); -be_define_const_str(toupper, "toupper", 3691983576u, 0, 7, NULL); -be_define_const_str(POST, "POST", 1929554311u, 0, 4, &be_const_str_SERIAL_6O2); -be_define_const_str(SERIAL_6O2, "SERIAL_6O2", 316486129u, 0, 10, &be_const_str_iter); -be_define_const_str(iter, "iter", 3124256359u, 0, 4, &be_const_str_load); -be_define_const_str(load, "load", 3859241449u, 0, 4, NULL); -be_define_const_str(available, "available", 1727918744u, 0, 9, &be_const_str_ceil); -be_define_const_str(ceil, "ceil", 1659167240u, 0, 4, &be_const_str_clear); -be_define_const_str(clear, "clear", 1550717474u, 0, 5, &be_const_str_digital_read); -be_define_const_str(digital_read, "digital_read", 3585496928u, 0, 12, NULL); -be_define_const_str(_get_cb, "_get_cb", 1448849122u, 0, 7, &be_const_str_bytes); -be_define_const_str(bytes, "bytes", 1706151940u, 0, 5, &be_const_str_settings); -be_define_const_str(settings, "settings", 1745255176u, 0, 8, NULL); -be_define_const_str(get_string, "get_string", 4195847969u, 0, 10, NULL); -be_define_const_str(asstring, "asstring", 1298225088u, 0, 8, &be_const_str_pin_used); -be_define_const_str(pin_used, "pin_used", 4033854612u, 0, 8, &be_const_str_pop); -be_define_const_str(pop, "pop", 1362321360u, 0, 3, NULL); -be_define_const_str(static, "static", 3532702267u, 71, 6, NULL); -be_define_const_str(AES_GCM, "AES_GCM", 3832208678u, 0, 7, &be_const_str_SERIAL_8N2); -be_define_const_str(SERIAL_8N2, "SERIAL_8N2", 2386074854u, 0, 10, NULL); -be_define_const_str(close, "close", 667630371u, 0, 5, &be_const_str_set_power); -be_define_const_str(set_power, "set_power", 549820893u, 0, 9, NULL); -be_define_const_str(find_op, "find_op", 3766713376u, 0, 7, NULL); -be_define_const_str(get, "get", 1410115415u, 0, 3, NULL); -be_define_const_str(print, "print", 372738696u, 0, 5, &be_const_str_publish_result); -be_define_const_str(publish_result, "publish_result", 2013351252u, 0, 14, NULL); -be_define_const_str(target_search, "target_search", 1947846553u, 0, 13, NULL); -be_define_const_str(_ccmd, "_ccmd", 2163421413u, 0, 5, &be_const_str_fromb64); -be_define_const_str(fromb64, "fromb64", 2717019639u, 0, 7, &be_const_str_module); -be_define_const_str(module, "module", 3617558685u, 0, 6, NULL); -be_define_const_str(allocated, "allocated", 429986098u, 0, 9, NULL); -be_define_const_str(GET, "GET", 2531704439u, 0, 3, NULL); -be_define_const_str(SERIAL_8E1, "SERIAL_8E1", 2371121616u, 0, 10, &be_const_str_classof); -be_define_const_str(classof, "classof", 1796577762u, 0, 7, &be_const_str_cos); -be_define_const_str(cos, "cos", 4220379804u, 0, 3, NULL); -be_define_const_str(assert, "assert", 2774883451u, 0, 6, &be_const_str_content_send); -be_define_const_str(content_send, "content_send", 1673733649u, 0, 12, &be_const_str_read13); -be_define_const_str(read13, "read13", 12887293u, 0, 6, &be_const_str_reverse); -be_define_const_str(reverse, "reverse", 558918661u, 0, 7, &be_const_str_set_timer); -be_define_const_str(set_timer, "set_timer", 2135414533u, 0, 9, &be_const_str_class); -be_define_const_str(class, "class", 2872970239u, 57, 5, NULL); -be_define_const_str(codedump, "codedump", 1786337906u, 0, 8, &be_const_str_isrunning); -be_define_const_str(isrunning, "isrunning", 1688182268u, 0, 9, &be_const_str_publish); -be_define_const_str(publish, "publish", 264247304u, 0, 7, &be_const_str_range); -be_define_const_str(range, "range", 4208725202u, 0, 5, &be_const_str_write); -be_define_const_str(write, "write", 3190202204u, 0, 5, NULL); -be_define_const_str(opt_connect, "..", 2748622605u, 0, 2, &be_const_str_SERIAL_7O1); -be_define_const_str(SERIAL_7O1, "SERIAL_7O1", 1823802675u, 0, 10, NULL); -be_define_const_str(update, "update", 672109684u, 0, 6, NULL); -be_define_const_str(_cmd, "_cmd", 3419822142u, 0, 4, &be_const_str_isnan); -be_define_const_str(isnan, "isnan", 2981347434u, 0, 5, &be_const_str_resp_cmnd_failed); -be_define_const_str(resp_cmnd_failed, "resp_cmnd_failed", 2136281562u, 0, 16, NULL); -be_define_const_str(SERIAL_5O1, "SERIAL_5O1", 3782657917u, 0, 10, &be_const_str_abs); -be_define_const_str(abs, "abs", 709362235u, 0, 3, NULL); -be_define_const_str(SERIAL_7E2, "SERIAL_7E2", 97385204u, 0, 10, NULL); -be_define_const_str(SERIAL_6N1, "SERIAL_6N1", 198895701u, 0, 10, &be_const_str__cb); -be_define_const_str(_cb, "_cb", 4043300367u, 0, 3, &be_const_str_depower); -be_define_const_str(depower, "depower", 3563819571u, 0, 7, NULL); -be_define_const_str(Tasmota, "Tasmota", 4047617668u, 0, 7, &be_const_str_item); -be_define_const_str(item, "item", 2671260646u, 0, 4, &be_const_str_set_useragent); -be_define_const_str(set_useragent, "set_useragent", 612237244u, 0, 13, &be_const_str_wire2); -be_define_const_str(wire2, "wire2", 3229499038u, 0, 5, NULL); -be_define_const_str(time_reached, "time_reached", 2075136773u, 0, 12, NULL); -be_define_const_str(chars_in_string, "chars_in_string", 3148785132u, 0, 15, &be_const_str_false); -be_define_const_str(false, "false", 184981848u, 62, 5, NULL); -be_define_const_str(add_rule, "add_rule", 596540743u, 0, 8, &be_const_str_setbits); -be_define_const_str(setbits, "setbits", 2762408167u, 0, 7, &be_const_str_write_file); -be_define_const_str(write_file, "write_file", 3177658879u, 0, 10, NULL); -be_define_const_str(hs2rgb, "hs2rgb", 1040816349u, 0, 6, NULL); -be_define_const_str(SERIAL_8O1, "SERIAL_8O1", 289122742u, 0, 10, &be_const_str_wd); -be_define_const_str(wd, "wd", 1531424278u, 0, 2, &be_const_str_wire_scan); -be_define_const_str(wire_scan, "wire_scan", 2671275880u, 0, 9, NULL); -be_define_const_str(AudioFileSourceFS, "AudioFileSourceFS", 1839147653u, 0, 17, &be_const_str_get_free_heap); -be_define_const_str(get_free_heap, "get_free_heap", 625069757u, 0, 13, NULL); -be_define_const_str(AudioGenerator, "AudioGenerator", 1839297342u, 0, 14, &be_const_str_SERIAL_5E2); -be_define_const_str(SERIAL_5E2, "SERIAL_5E2", 1180552854u, 0, 10, NULL); -be_define_const_str(_global_addr, "_global_addr", 533766721u, 0, 12, &be_const_str_content_send_style); -be_define_const_str(content_send_style, "content_send_style", 1087907647u, 0, 18, &be_const_str_remove_timer); -be_define_const_str(remove_timer, "remove_timer", 4141472215u, 0, 12, &be_const_str_tr); -be_define_const_str(tr, "tr", 1195724803u, 0, 2, NULL); -be_define_const_str(dot_w, ".w", 1255414514u, 0, 2, NULL); -be_define_const_str(MD5, "MD5", 1935726387u, 0, 3, NULL); -be_define_const_str(break, "break", 3378807160u, 58, 5, NULL); +be_define_const_str(pow, "pow", 1479764693u, 0, 3, &be_const_str_remove); +be_define_const_str(remove, "remove", 3683784189u, 0, 6, &be_const_str_remove_timer); +be_define_const_str(remove_timer, "remove_timer", 4141472215u, 0, 12, NULL); +be_define_const_str(MD5, "MD5", 1935726387u, 0, 3, &be_const_str__ccmd); +be_define_const_str(_ccmd, "_ccmd", 2163421413u, 0, 5, &be_const_str_digital_write); be_define_const_str(digital_write, "digital_write", 3435877979u, 0, 13, NULL); -be_define_const_str(asin, "asin", 4272848550u, 0, 4, NULL); -be_define_const_str(_def, "_def", 1985022181u, 0, 4, &be_const_str_exec_cmd); -be_define_const_str(exec_cmd, "exec_cmd", 493567399u, 0, 8, &be_const_str_exists); -be_define_const_str(exists, "exists", 1002329533u, 0, 6, &be_const_str_flush); -be_define_const_str(flush, "flush", 3002334877u, 0, 5, &be_const_str_as); -be_define_const_str(as, "as", 1579491469u, 67, 2, NULL); -be_define_const_str(set_light, "set_light", 3176076152u, 0, 9, &be_const_str_time_str); -be_define_const_str(time_str, "time_str", 2613827612u, 0, 8, NULL); -be_define_const_str(arg_size, "arg_size", 3310243257u, 0, 8, &be_const_str_bus); -be_define_const_str(bus, "bus", 1607822841u, 0, 3, NULL); -be_define_const_str(opt_eq, "==", 2431966415u, 0, 2, &be_const_str_try_rule); -be_define_const_str(try_rule, "try_rule", 1986449405u, 0, 8, NULL); -be_define_const_str(kv, "kv", 1497177492u, 0, 2, &be_const_str_reverse_gamma10); -be_define_const_str(reverse_gamma10, "reverse_gamma10", 739112262u, 0, 15, NULL); -be_define_const_str(tostring, "tostring", 2299708645u, 0, 8, NULL); -be_define_const_str(format, "format", 3114108242u, 0, 6, &be_const_str_tob64); -be_define_const_str(tob64, "tob64", 373777640u, 0, 5, &be_const_str_continue); -be_define_const_str(continue, "continue", 2977070660u, 59, 8, NULL); -be_define_const_str(log, "log", 1062293841u, 0, 3, NULL); -be_define_const_str(SERIAL_7N1, "SERIAL_7N1", 1891060246u, 0, 10, &be_const_str_lower); -be_define_const_str(lower, "lower", 3038577850u, 0, 5, NULL); -be_define_const_str(stop, "stop", 3411225317u, 0, 4, NULL); -be_define_const_str(count, "count", 967958004u, 0, 5, &be_const_str_encrypt); -be_define_const_str(encrypt, "encrypt", 2194327650u, 0, 7, &be_const_str_resp_cmnd_str); -be_define_const_str(resp_cmnd_str, "resp_cmnd_str", 737845590u, 0, 13, NULL); -be_define_const_str(byte, "byte", 1683620383u, 0, 4, NULL); -be_define_const_str(fromstring, "fromstring", 610302344u, 0, 10, &be_const_str_run_deferred); -be_define_const_str(run_deferred, "run_deferred", 371594696u, 0, 12, &be_const_str_setitem); -be_define_const_str(setitem, "setitem", 1554834596u, 0, 7, NULL); -be_define_const_str(cmd, "cmd", 4136785899u, 0, 3, &be_const_str_event); -be_define_const_str(event, "event", 4264611999u, 0, 5, NULL); -be_define_const_str(SERIAL_6E1, "SERIAL_6E1", 334249486u, 0, 10, &be_const_str_SERIAL_6O1); -be_define_const_str(SERIAL_6O1, "SERIAL_6O1", 266153272u, 0, 10, &be_const_str_remove_driver); -be_define_const_str(remove_driver, "remove_driver", 1030243768u, 0, 13, NULL); -be_define_const_str(EC_C25519, "EC_C25519", 95492591u, 0, 9, NULL); -be_define_const_str(read12, "read12", 4291076970u, 0, 6, NULL); -be_define_const_str(_write, "_write", 2215462825u, 0, 6, NULL); -be_define_const_str(opt_call, "()", 685372826u, 0, 2, &be_const_str_AudioOutput); -be_define_const_str(AudioOutput, "AudioOutput", 3257792048u, 0, 11, &be_const_str_attrdump); -be_define_const_str(attrdump, "attrdump", 1521571304u, 0, 8, &be_const_str_int); -be_define_const_str(int, "int", 2515107422u, 0, 3, NULL); -be_define_const_str(AudioGeneratorMP3, "AudioGeneratorMP3", 2199818488u, 0, 17, &be_const_str_add_header); -be_define_const_str(add_header, "add_header", 927130612u, 0, 10, NULL); -be_define_const_str(ctypes_bytes_dyn, "ctypes_bytes_dyn", 915205307u, 0, 16, &be_const_str_keys); -be_define_const_str(keys, "keys", 4182378701u, 0, 4, NULL); -be_define_const_str(set_auth, "set_auth", 1057170930u, 0, 8, &be_const_str_def); -be_define_const_str(def, "def", 3310976652u, 55, 3, NULL); -be_define_const_str(, "", 2166136261u, 0, 0, &be_const_str_SERIAL_5N2); -be_define_const_str(SERIAL_5N2, "SERIAL_5N2", 3363364537u, 0, 10, &be_const_str__rules); -be_define_const_str(_rules, "_rules", 4266217105u, 0, 6, &be_const_str_has); -be_define_const_str(has, "has", 3988721635u, 0, 3, &be_const_str_set); -be_define_const_str(set, "set", 3324446467u, 0, 3, NULL); -be_define_const_str(public_key, "public_key", 4169142980u, 0, 10, NULL); -be_define_const_str(get_power, "get_power", 3009799377u, 0, 9, &be_const_str_type); -be_define_const_str(type, "type", 1361572173u, 0, 4, NULL); -be_define_const_str(opt_add, "+", 772578730u, 0, 1, &be_const_str_dot_size); -be_define_const_str(dot_size, ".size", 1965188224u, 0, 5, &be_const_str_set_timeouts); -be_define_const_str(set_timeouts, "set_timeouts", 3732850900u, 0, 12, &be_const_str_tomap); -be_define_const_str(tomap, "tomap", 612167626u, 0, 5, NULL); -be_define_const_str(getbits, "getbits", 3094168979u, 0, 7, &be_const_str_sinh); -be_define_const_str(sinh, "sinh", 282220607u, 0, 4, &be_const_str_sqrt); -be_define_const_str(sqrt, "sqrt", 2112764879u, 0, 4, NULL); -be_define_const_str(dot_p1, ".p1", 249175686u, 0, 3, &be_const_str_begin); -be_define_const_str(begin, "begin", 1748273790u, 0, 5, &be_const_str_delay); -be_define_const_str(delay, "delay", 1322381784u, 0, 5, &be_const_str_scan); -be_define_const_str(scan, "scan", 3974641896u, 0, 4, &be_const_str_for); -be_define_const_str(for, "for", 2901640080u, 54, 3, NULL); -be_define_const_str(read8, "read8", 2802788167u, 0, 5, NULL); -be_define_const_str(AudioGeneratorWAV, "AudioGeneratorWAV", 2746509368u, 0, 17, &be_const_str_get_light); -be_define_const_str(get_light, "get_light", 381930476u, 0, 9, NULL); -be_define_const_str(_global_def, "_global_def", 646007001u, 0, 11, &be_const_str_map); -be_define_const_str(map, "map", 3751997361u, 0, 3, &be_const_str_redirect); -be_define_const_str(redirect, "redirect", 389758641u, 0, 8, NULL); -be_define_const_str(_ptr, "_ptr", 306235816u, 0, 4, &be_const_str_isinstance); -be_define_const_str(isinstance, "isinstance", 3669352738u, 0, 10, NULL); -be_define_const_str(pin, "pin", 1866532500u, 0, 3, &be_const_str_size); -be_define_const_str(size, "size", 597743964u, 0, 4, &be_const_str_state); -be_define_const_str(state, "state", 2016490230u, 0, 5, NULL); -be_define_const_str(dot_p, ".p", 1171526419u, 0, 2, &be_const_str__drivers); -be_define_const_str(_drivers, "_drivers", 3260328985u, 0, 8, &be_const_str_erase); -be_define_const_str(erase, "erase", 1010949589u, 0, 5, NULL); -be_define_const_str(I2C_Driver, "I2C_Driver", 1714501658u, 0, 10, &be_const_str_addr); -be_define_const_str(addr, "addr", 1087856498u, 0, 4, &be_const_str_copy); -be_define_const_str(copy, "copy", 3848464964u, 0, 4, &be_const_str_find_key_i); -be_define_const_str(find_key_i, "find_key_i", 850136726u, 0, 10, &be_const_str_pin_mode); -be_define_const_str(pin_mode, "pin_mode", 3258314030u, 0, 8, &be_const_str_setrange); -be_define_const_str(setrange, "setrange", 3794019032u, 0, 8, NULL); -be_define_const_str(SERIAL_8N1, "SERIAL_8N1", 2369297235u, 0, 10, &be_const_str_char); -be_define_const_str(char, "char", 2823553821u, 0, 4, &be_const_str_concat); -be_define_const_str(concat, "concat", 4124019837u, 0, 6, &be_const_str_remove); -be_define_const_str(remove, "remove", 3683784189u, 0, 6, &be_const_str_serial); -be_define_const_str(serial, "serial", 3687697785u, 0, 6, NULL); -be_define_const_str(SERIAL_5O2, "SERIAL_5O2", 3732325060u, 0, 10, &be_const_str__read); -be_define_const_str(_read, "_read", 346717030u, 0, 5, &be_const_str_cmd_res); -be_define_const_str(cmd_res, "cmd_res", 921166762u, 0, 7, &be_const_str_contains); -be_define_const_str(contains, "contains", 1825239352u, 0, 8, &be_const_str_imax); -be_define_const_str(imax, "imax", 3084515410u, 0, 4, &be_const_str_super); -be_define_const_str(super, "super", 4152230356u, 0, 5, &be_const_str_try); -be_define_const_str(try, "try", 2887626766u, 68, 3, NULL); -be_define_const_str(last_modified, "last_modified", 772177145u, 0, 13, &be_const_str_return); -be_define_const_str(return, "return", 2246981567u, 60, 6, NULL); -be_define_const_str(SERIAL_6N2, "SERIAL_6N2", 148562844u, 0, 10, NULL); -be_define_const_str(call, "call", 3018949801u, 0, 4, &be_const_str_resize); -be_define_const_str(resize, "resize", 3514612129u, 0, 6, NULL); -be_define_const_str(escape, "escape", 2652972038u, 0, 6, NULL); -be_define_const_str(upper, "upper", 176974407u, 0, 5, NULL); -be_define_const_str(end, "end", 1787721130u, 56, 3, NULL); -be_define_const_str(gamma8, "gamma8", 3802843830u, 0, 6, &be_const_str_memory); -be_define_const_str(memory, "memory", 2229924270u, 0, 6, &be_const_str_wifi); -be_define_const_str(wifi, "wifi", 120087624u, 0, 4, NULL); -be_define_const_str(yield, "yield", 1821831854u, 0, 5, NULL); -be_define_const_str(get_option, "get_option", 2123730033u, 0, 10, &be_const_str_init); -be_define_const_str(init, "init", 380752755u, 0, 4, &be_const_str_read); -be_define_const_str(read, "read", 3470762949u, 0, 4, NULL); -be_define_const_str(_settings_ptr, "_settings_ptr", 1825772182u, 0, 13, &be_const_str__timers); -be_define_const_str(_timers, "_timers", 2600100916u, 0, 7, &be_const_str_finish); -be_define_const_str(finish, "finish", 1494643858u, 0, 6, NULL); -be_define_const_str(__upper__, "__upper__", 3612202883u, 0, 9, &be_const_str_dump); -be_define_const_str(dump, "dump", 3663001223u, 0, 4, NULL); -be_define_const_str(save, "save", 3439296072u, 0, 4, NULL); -be_define_const_str(__lower__, "__lower__", 123855590u, 0, 9, &be_const_str_listdir); -be_define_const_str(listdir, "listdir", 2005220720u, 0, 7, NULL); -be_define_const_str(check_privileged_access, "check_privileged_access", 3692933968u, 0, 23, &be_const_str_rand); -be_define_const_str(rand, "rand", 2711325910u, 0, 4, &be_const_str_web_send); -be_define_const_str(web_send, "web_send", 2989941448u, 0, 8, NULL); -be_define_const_str(i2c_enabled, "i2c_enabled", 218388101u, 0, 11, &be_const_str_wire1); -be_define_const_str(wire1, "wire1", 3212721419u, 0, 5, NULL); -be_define_const_str(dac_voltage, "dac_voltage", 1552257222u, 0, 11, &be_const_str_imin); -be_define_const_str(imin, "imin", 2714127864u, 0, 4, &be_const_str_log10); -be_define_const_str(log10, "log10", 2346846000u, 0, 5, &be_const_str_skip); -be_define_const_str(skip, "skip", 1097563074u, 0, 4, &be_const_str_else); -be_define_const_str(else, "else", 3183434736u, 52, 4, &be_const_str_except); -be_define_const_str(except, "except", 950914032u, 69, 6, &be_const_str_nil); -be_define_const_str(nil, "nil", 228849900u, 63, 3, NULL); -be_define_const_str(resp_cmnd_error, "resp_cmnd_error", 2404088863u, 0, 15, NULL); -be_define_const_str(calldepth, "calldepth", 3122364302u, 0, 9, &be_const_str_do); -be_define_const_str(do, "do", 1646057492u, 65, 2, NULL); -be_define_const_str(__iterator__, "__iterator__", 3884039703u, 0, 12, &be_const_str_true); -be_define_const_str(true, "true", 1303515621u, 61, 4, NULL); -be_define_const_str(rad, "rad", 1358899048u, 0, 3, &be_const_str_import); -be_define_const_str(import, "import", 288002260u, 66, 6, NULL); -be_define_const_str(SERIAL_8O2, "SERIAL_8O2", 272345123u, 0, 10, &be_const_str_gamma10); -be_define_const_str(gamma10, "gamma10", 3472052483u, 0, 7, &be_const_str_elif); -be_define_const_str(elif, "elif", 3232090307u, 51, 4, NULL); -be_define_const_str(resp_cmnd, "resp_cmnd", 2869459626u, 0, 9, &be_const_str_shared_key); -be_define_const_str(shared_key, "shared_key", 2200833624u, 0, 10, &be_const_str_web_send_decimal); -be_define_const_str(web_send_decimal, "web_send_decimal", 1407210204u, 0, 16, &be_const_str_write8); -be_define_const_str(write8, "write8", 3133991532u, 0, 6, NULL); -be_define_const_str(SERIAL_5E1, "SERIAL_5E1", 1163775235u, 0, 10, &be_const_str_member); -be_define_const_str(member, "member", 719708611u, 0, 6, &be_const_str_sin); -be_define_const_str(sin, "sin", 3761252941u, 0, 3, NULL); -be_define_const_str(OneWire, "OneWire", 2298990722u, 0, 7, &be_const_str_SERIAL_7O2); -be_define_const_str(SERIAL_7O2, "SERIAL_7O2", 1840580294u, 0, 10, &be_const_str__begin_transmission); -be_define_const_str(_begin_transmission, "_begin_transmission", 2779461176u, 0, 19, &be_const_str_get_switch); -be_define_const_str(get_switch, "get_switch", 164821028u, 0, 10, &be_const_str_name); -be_define_const_str(name, "name", 2369371622u, 0, 4, &be_const_str_nan); -be_define_const_str(nan, "nan", 797905850u, 0, 3, NULL); -be_define_const_str(add, "add", 993596020u, 0, 3, &be_const_str_eth); -be_define_const_str(eth, "eth", 2191266556u, 0, 3, &be_const_str_find); -be_define_const_str(find, "find", 3186656602u, 0, 4, &be_const_str_read32); -be_define_const_str(read32, "read32", 1741276240u, 0, 6, &be_const_str_remove_cmd); -be_define_const_str(remove_cmd, "remove_cmd", 3832315702u, 0, 10, NULL); -be_define_const_str(gc, "gc", 1042313471u, 0, 2, &be_const_str_reset_search); -be_define_const_str(reset_search, "reset_search", 1350414305u, 0, 12, NULL); -be_define_const_str(content_stop, "content_stop", 658554751u, 0, 12, NULL); -be_define_const_str(counters, "counters", 4095866864u, 0, 8, &be_const_str_detect); -be_define_const_str(detect, "detect", 8884370u, 0, 6, &be_const_str_exp); -be_define_const_str(exp, "exp", 1923516200u, 0, 3, &be_const_str_on); -be_define_const_str(on, "on", 1630810064u, 0, 2, NULL); -be_define_const_str(arg, "arg", 1047474471u, 0, 3, &be_const_str_reduce); -be_define_const_str(reduce, "reduce", 2002030311u, 0, 6, &be_const_str_split); -be_define_const_str(split, "split", 2276994531u, 0, 5, &be_const_str_strftime); -be_define_const_str(strftime, "strftime", 187738851u, 0, 8, &be_const_str_raise); +be_define_const_str(dot_p2, ".p2", 232398067u, 0, 3, &be_const_str_floor); +be_define_const_str(floor, "floor", 3102149661u, 0, 5, &be_const_str_input); +be_define_const_str(input, "input", 4191711099u, 0, 5, &be_const_str_range); +be_define_const_str(range, "range", 4208725202u, 0, 5, NULL); +be_define_const_str(atan, "atan", 108579519u, 0, 4, &be_const_str_find_op); +be_define_const_str(find_op, "find_op", 3766713376u, 0, 7, NULL); +be_define_const_str(SERIAL_6N1, "SERIAL_6N1", 198895701u, 0, 10, &be_const_str_classname); +be_define_const_str(classname, "classname", 1998589948u, 0, 9, NULL); +be_define_const_str(content_start, "content_start", 2937509069u, 0, 13, &be_const_str_import); +be_define_const_str(import, "import", 288002260u, 66, 6, &be_const_str_raise); be_define_const_str(raise, "raise", 1593437475u, 70, 5, NULL); -be_define_const_str(AudioOutputI2S, "AudioOutputI2S", 638031784u, 0, 14, &be_const_str_if); -be_define_const_str(if, "if", 959999494u, 50, 2, NULL); -be_define_const_str(cb_dispatch, "cb_dispatch", 1741510499u, 0, 11, &be_const_str_exec_tele); -be_define_const_str(exec_tele, "exec_tele", 1020751601u, 0, 9, &be_const_str_srand); -be_define_const_str(srand, "srand", 465518633u, 0, 5, NULL); -be_define_const_str(write_bytes, "write_bytes", 1227543792u, 0, 11, NULL); -be_define_const_str(_settings_def, "_settings_def", 3775560307u, 0, 13, NULL); -be_define_const_str(cosh, "cosh", 4099687964u, 0, 4, &be_const_str_pi); -be_define_const_str(pi, "pi", 1213090802u, 0, 2, &be_const_str_remove_rule); -be_define_const_str(remove_rule, "remove_rule", 3456211328u, 0, 11, &be_const_str_scale_uint); -be_define_const_str(scale_uint, "scale_uint", 3090811094u, 0, 10, &be_const_str_var); -be_define_const_str(var, "var", 2317739966u, 64, 3, NULL); -be_define_const_str(SERIAL_8E2, "SERIAL_8E2", 2421454473u, 0, 10, &be_const_str_acos); -be_define_const_str(acos, "acos", 1006755615u, 0, 4, &be_const_str_gen_cb); -be_define_const_str(gen_cb, "gen_cb", 3245227551u, 0, 6, &be_const_str_read_bytes); -be_define_const_str(read_bytes, "read_bytes", 3576733173u, 0, 10, NULL); -be_define_const_str(AudioFileSource, "AudioFileSource", 2959980058u, 0, 15, &be_const_str_SERIAL_5N1); -be_define_const_str(SERIAL_5N1, "SERIAL_5N1", 3313031680u, 0, 10, &be_const_str_wire); -be_define_const_str(wire, "wire", 4082753944u, 0, 4, &be_const_str_while); -be_define_const_str(while, "while", 231090382u, 53, 5, NULL); -be_define_const_str(SERIAL_7N2, "SERIAL_7N2", 1874282627u, 0, 10, &be_const_str_get_size); -be_define_const_str(get_size, "get_size", 2803644713u, 0, 8, NULL); -be_define_const_str(exec_rules, "exec_rules", 1445221092u, 0, 10, NULL); -be_define_const_str(_available, "_available", 1306196581u, 0, 10, &be_const_str_search); -be_define_const_str(search, "search", 2150836393u, 0, 6, NULL); -be_define_const_str(global, "global", 503252654u, 0, 6, NULL); -be_define_const_str(collect, "collect", 2399039025u, 0, 7, &be_const_str_input); -be_define_const_str(input, "input", 4191711099u, 0, 5, &be_const_str_response_append); +be_define_const_str(SERIAL_8N2, "SERIAL_8N2", 2386074854u, 0, 10, &be_const_str_keys); +be_define_const_str(keys, "keys", 4182378701u, 0, 4, NULL); +be_define_const_str(content_send_style, "content_send_style", 1087907647u, 0, 18, &be_const_str_static); +be_define_const_str(static, "static", 3532702267u, 71, 6, NULL); +be_define_const_str(_begin_transmission, "_begin_transmission", 2779461176u, 0, 19, &be_const_str__request_from); +be_define_const_str(_request_from, "_request_from", 3965148604u, 0, 13, &be_const_str_isnan); +be_define_const_str(isnan, "isnan", 2981347434u, 0, 5, &be_const_str_reverse_gamma10); +be_define_const_str(reverse_gamma10, "reverse_gamma10", 739112262u, 0, 15, NULL); +be_define_const_str(number, "number", 467038368u, 0, 6, &be_const_str_resp_cmnd_str); +be_define_const_str(resp_cmnd_str, "resp_cmnd_str", 737845590u, 0, 13, &be_const_str_run_deferred); +be_define_const_str(run_deferred, "run_deferred", 371594696u, 0, 12, NULL); +be_define_const_str(exec_rules, "exec_rules", 1445221092u, 0, 10, &be_const_str_web_send); +be_define_const_str(web_send, "web_send", 2989941448u, 0, 8, NULL); +be_define_const_str(GET, "GET", 2531704439u, 0, 3, &be_const_str__rules); +be_define_const_str(_rules, "_rules", 4266217105u, 0, 6, &be_const_str_begin); +be_define_const_str(begin, "begin", 1748273790u, 0, 5, &be_const_str_escape); +be_define_const_str(escape, "escape", 2652972038u, 0, 6, NULL); +be_define_const_str(I2C_Driver, "I2C_Driver", 1714501658u, 0, 10, &be_const_str_char); +be_define_const_str(char, "char", 2823553821u, 0, 4, NULL); +be_define_const_str(opt_neq, "!=", 2428715011u, 0, 2, &be_const_str_Wire); +be_define_const_str(Wire, "Wire", 1938276536u, 0, 4, &be_const_str_asstring); +be_define_const_str(asstring, "asstring", 1298225088u, 0, 8, &be_const_str_strftime); +be_define_const_str(strftime, "strftime", 187738851u, 0, 8, NULL); +be_define_const_str(last_modified, "last_modified", 772177145u, 0, 13, &be_const_str_set); +be_define_const_str(set, "set", 3324446467u, 0, 3, NULL); +be_define_const_str(add, "add", 993596020u, 0, 3, &be_const_str_eth); +be_define_const_str(eth, "eth", 2191266556u, 0, 3, &be_const_str_publish); +be_define_const_str(publish, "publish", 264247304u, 0, 7, NULL); +be_define_const_str(rtc, "rtc", 1070575216u, 0, 3, &be_const_str_scan); +be_define_const_str(scan, "scan", 3974641896u, 0, 4, NULL); +be_define_const_str(EC_C25519, "EC_C25519", 95492591u, 0, 9, &be_const_str_nil); +be_define_const_str(nil, "nil", 228849900u, 63, 3, NULL); +be_define_const_str(ceil, "ceil", 1659167240u, 0, 4, &be_const_str_item); +be_define_const_str(item, "item", 2671260646u, 0, 4, NULL); +be_define_const_str(log, "log", 1062293841u, 0, 3, NULL); +be_define_const_str(_global_def, "_global_def", 646007001u, 0, 11, &be_const_str_clear); +be_define_const_str(clear, "clear", 1550717474u, 0, 5, NULL); +be_define_const_str(atan2, "atan2", 3173440503u, 0, 5, &be_const_str_dump); +be_define_const_str(dump, "dump", 3663001223u, 0, 4, &be_const_str_fromb64); +be_define_const_str(fromb64, "fromb64", 2717019639u, 0, 7, NULL); +be_define_const_str(deinit, "deinit", 2345559592u, 0, 6, &be_const_str_read13); +be_define_const_str(read13, "read13", 12887293u, 0, 6, NULL); +be_define_const_str(SERIAL_8O1, "SERIAL_8O1", 289122742u, 0, 10, NULL); +be_define_const_str(SERIAL_6O1, "SERIAL_6O1", 266153272u, 0, 10, &be_const_str_add_rule); +be_define_const_str(add_rule, "add_rule", 596540743u, 0, 8, &be_const_str_fromstring); +be_define_const_str(fromstring, "fromstring", 610302344u, 0, 10, NULL); +be_define_const_str(SERIAL_6E2, "SERIAL_6E2", 317471867u, 0, 10, &be_const_str_try_rule); +be_define_const_str(try_rule, "try_rule", 1986449405u, 0, 8, NULL); +be_define_const_str(gc, "gc", 1042313471u, 0, 2, &be_const_str_publish_result); +be_define_const_str(publish_result, "publish_result", 2013351252u, 0, 14, &be_const_str_response_append); be_define_const_str(response_append, "response_append", 450346371u, 0, 15, NULL); -be_define_const_str(str, "str", 3259748752u, 0, 3, NULL); -be_define_const_str(SERIAL_6E2, "SERIAL_6E2", 317471867u, 0, 10, &be_const_str_SERIAL_7E1); -be_define_const_str(SERIAL_7E1, "SERIAL_7E1", 147718061u, 0, 10, &be_const_str_content_button); -be_define_const_str(content_button, "content_button", 1956476087u, 0, 14, NULL); -be_define_const_str(number, "number", 467038368u, 0, 6, &be_const_str_tanh); -be_define_const_str(tanh, "tanh", 153638352u, 0, 4, &be_const_str_toptr); -be_define_const_str(toptr, "toptr", 3379847454u, 0, 5, &be_const_str_write_bit); -be_define_const_str(write_bit, "write_bit", 2660990436u, 0, 9, NULL); -be_define_const_str(add_cmd, "add_cmd", 3361630879u, 0, 7, &be_const_str_select); -be_define_const_str(select, "select", 297952813u, 0, 6, &be_const_str_traceback); -be_define_const_str(traceback, "traceback", 3385188109u, 0, 9, NULL); -be_define_const_str(atan2, "atan2", 3173440503u, 0, 5, &be_const_str_loop); -be_define_const_str(loop, "loop", 3723446379u, 0, 4, &be_const_str_millis); -be_define_const_str(millis, "millis", 1214679063u, 0, 6, &be_const_str_url_encode); -be_define_const_str(url_encode, "url_encode", 528392145u, 0, 10, NULL); -be_define_const_str(_end_transmission, "_end_transmission", 3237480400u, 0, 17, &be_const_str_deinit); -be_define_const_str(deinit, "deinit", 2345559592u, 0, 6, &be_const_str_tan); -be_define_const_str(tan, "tan", 2633446552u, 0, 3, NULL); -be_define_const_str(geti, "geti", 2381006490u, 0, 4, &be_const_str_seti); -be_define_const_str(seti, "seti", 1500556254u, 0, 4, NULL); -be_define_const_str(_buffer, "_buffer", 2044888568u, 0, 7, NULL); -be_define_const_str(atan, "atan", 108579519u, 0, 4, &be_const_str_content_flush); -be_define_const_str(content_flush, "content_flush", 214922475u, 0, 13, &be_const_str_list); -be_define_const_str(list, "list", 217798785u, 0, 4, &be_const_str_tolower); -be_define_const_str(tolower, "tolower", 1042520049u, 0, 7, NULL); -be_define_const_str(dot_len, ".len", 850842136u, 0, 4, &be_const_str__request_from); -be_define_const_str(_request_from, "_request_from", 3965148604u, 0, 13, &be_const_str_has_arg); -be_define_const_str(has_arg, "has_arg", 424878688u, 0, 7, NULL); -be_define_const_str(pow, "pow", 1479764693u, 0, 3, &be_const_str_push); -be_define_const_str(push, "push", 2272264157u, 0, 4, &be_const_str_read24); -be_define_const_str(read24, "read24", 1808533811u, 0, 6, NULL); -be_define_const_str(enabled, "enabled", 49525662u, 0, 7, &be_const_str_webclient); +be_define_const_str(continue, "continue", 2977070660u, 59, 8, NULL); +be_define_const_str(dot_p1, ".p1", 249175686u, 0, 3, &be_const_str__def); +be_define_const_str(_def, "_def", 1985022181u, 0, 4, &be_const_str_imin); +be_define_const_str(imin, "imin", 2714127864u, 0, 4, NULL); +be_define_const_str(chars_in_string, "chars_in_string", 3148785132u, 0, 15, &be_const_str_concat); +be_define_const_str(concat, "concat", 4124019837u, 0, 6, &be_const_str_content_stop); +be_define_const_str(content_stop, "content_stop", 658554751u, 0, 12, &be_const_str_def); +be_define_const_str(def, "def", 3310976652u, 55, 3, NULL); +be_define_const_str(traceback, "traceback", 3385188109u, 0, 9, &be_const_str_wire); +be_define_const_str(wire, "wire", 4082753944u, 0, 4, NULL); +be_define_const_str(calldepth, "calldepth", 3122364302u, 0, 9, NULL); +be_define_const_str(finish, "finish", 1494643858u, 0, 6, &be_const_str_log10); +be_define_const_str(log10, "log10", 2346846000u, 0, 5, &be_const_str_name); +be_define_const_str(name, "name", 2369371622u, 0, 4, &be_const_str_time_str); +be_define_const_str(time_str, "time_str", 2613827612u, 0, 8, &be_const_str_do); +be_define_const_str(do, "do", 1646057492u, 65, 2, NULL); +be_define_const_str(read, "read", 3470762949u, 0, 4, &be_const_str_set_auth); +be_define_const_str(set_auth, "set_auth", 1057170930u, 0, 8, NULL); +be_define_const_str(Tasmota, "Tasmota", 4047617668u, 0, 7, NULL); +be_define_const_str(SERIAL_7E2, "SERIAL_7E2", 97385204u, 0, 10, &be_const_str_resolvecmnd); +be_define_const_str(resolvecmnd, "resolvecmnd", 993361485u, 0, 11, NULL); +be_define_const_str(__lower__, "__lower__", 123855590u, 0, 9, &be_const_str_addr); +be_define_const_str(addr, "addr", 1087856498u, 0, 4, &be_const_str_gamma8); +be_define_const_str(gamma8, "gamma8", 3802843830u, 0, 6, NULL); +be_define_const_str(member, "member", 719708611u, 0, 6, &be_const_str_scale_uint); +be_define_const_str(scale_uint, "scale_uint", 3090811094u, 0, 10, NULL); +be_define_const_str(codedump, "codedump", 1786337906u, 0, 8, NULL); +be_define_const_str(opt_call, "()", 685372826u, 0, 2, &be_const_str_SERIAL_5N2); +be_define_const_str(SERIAL_5N2, "SERIAL_5N2", 3363364537u, 0, 10, NULL); +be_define_const_str(attrdump, "attrdump", 1521571304u, 0, 8, &be_const_str_hex); +be_define_const_str(hex, "hex", 4273249610u, 0, 3, &be_const_str_remove_cmd); +be_define_const_str(remove_cmd, "remove_cmd", 3832315702u, 0, 10, NULL); +be_define_const_str(AudioOutput, "AudioOutput", 3257792048u, 0, 11, &be_const_str_break); +be_define_const_str(break, "break", 3378807160u, 58, 5, NULL); +be_define_const_str(SERIAL_5O1, "SERIAL_5O1", 3782657917u, 0, 10, &be_const_str_rand); +be_define_const_str(rand, "rand", 2711325910u, 0, 4, &be_const_str_class); +be_define_const_str(class, "class", 2872970239u, 57, 5, NULL); +be_define_const_str(public_key, "public_key", 4169142980u, 0, 10, &be_const_str_search); +be_define_const_str(search, "search", 2150836393u, 0, 6, &be_const_str_update); +be_define_const_str(update, "update", 672109684u, 0, 6, &be_const_str_end); +be_define_const_str(end, "end", 1787721130u, 56, 3, NULL); +be_define_const_str(i2c_enabled, "i2c_enabled", 218388101u, 0, 11, &be_const_str_read_bytes); +be_define_const_str(read_bytes, "read_bytes", 3576733173u, 0, 10, NULL); +be_define_const_str(fromptr, "fromptr", 666189689u, 0, 7, &be_const_str_pin_used); +be_define_const_str(pin_used, "pin_used", 4033854612u, 0, 8, &be_const_str_redirect); +be_define_const_str(redirect, "redirect", 389758641u, 0, 8, NULL); +be_define_const_str(_drivers, "_drivers", 3260328985u, 0, 8, &be_const_str_get_size); +be_define_const_str(get_size, "get_size", 2803644713u, 0, 8, &be_const_str_set_power); +be_define_const_str(set_power, "set_power", 549820893u, 0, 9, NULL); +be_define_const_str(loop, "loop", 3723446379u, 0, 4, &be_const_str_read32); +be_define_const_str(read32, "read32", 1741276240u, 0, 6, NULL); +be_define_const_str(add_cmd, "add_cmd", 3361630879u, 0, 7, NULL); +be_define_const_str(_settings_ptr, "_settings_ptr", 1825772182u, 0, 13, &be_const_str_reset); +be_define_const_str(reset, "reset", 1695364032u, 0, 5, NULL); +be_define_const_str(_ptr, "_ptr", 306235816u, 0, 4, &be_const_str_detect); +be_define_const_str(detect, "detect", 8884370u, 0, 6, &be_const_str_reset_search); +be_define_const_str(reset_search, "reset_search", 1350414305u, 0, 12, NULL); +be_define_const_str(SERIAL_6E1, "SERIAL_6E1", 334249486u, 0, 10, &be_const_str__read); +be_define_const_str(_read, "_read", 346717030u, 0, 5, NULL); +be_define_const_str(true, "true", 1303515621u, 61, 4, NULL); +be_define_const_str(opt_eq, "==", 2431966415u, 0, 2, &be_const_str_add_driver); +be_define_const_str(add_driver, "add_driver", 1654458371u, 0, 10, &be_const_str_tob64); +be_define_const_str(tob64, "tob64", 373777640u, 0, 5, &be_const_str_wire1); +be_define_const_str(wire1, "wire1", 3212721419u, 0, 5, NULL); +be_define_const_str(_timers, "_timers", 2600100916u, 0, 7, NULL); +be_define_const_str(opt_connect, "..", 2748622605u, 0, 2, &be_const_str_SERIAL_5E1); +be_define_const_str(SERIAL_5E1, "SERIAL_5E1", 1163775235u, 0, 10, &be_const_str_select); +be_define_const_str(select, "select", 297952813u, 0, 6, &be_const_str_setbits); +be_define_const_str(setbits, "setbits", 2762408167u, 0, 7, &be_const_str_webclient); be_define_const_str(webclient, "webclient", 4076389146u, 0, 9, NULL); -be_define_const_str(opt_neq, "!=", 2428715011u, 0, 2, &be_const_str_dot_p2); -be_define_const_str(dot_p2, ".p2", 232398067u, 0, 3, NULL); -be_define_const_str(Wire, "Wire", 1938276536u, 0, 4, &be_const_str_decrypt); -be_define_const_str(decrypt, "decrypt", 2886974618u, 0, 7, NULL); -be_define_const_str(floor, "floor", 3102149661u, 0, 5, &be_const_str_issubclass); -be_define_const_str(issubclass, "issubclass", 4078395519u, 0, 10, NULL); -be_define_const_str(classname, "classname", 1998589948u, 0, 9, &be_const_str_rtc); -be_define_const_str(rtc, "rtc", 1070575216u, 0, 3, NULL); -be_define_const_str(add_driver, "add_driver", 1654458371u, 0, 10, NULL); +be_define_const_str(deg, "deg", 3327754271u, 0, 3, &be_const_str_flush); +be_define_const_str(flush, "flush", 3002334877u, 0, 5, &be_const_str_hs2rgb); +be_define_const_str(hs2rgb, "hs2rgb", 1040816349u, 0, 6, NULL); +be_define_const_str(SERIAL_8E1, "SERIAL_8E1", 2371121616u, 0, 10, &be_const_str_setrange); +be_define_const_str(setrange, "setrange", 3794019032u, 0, 8, NULL); +be_define_const_str(dot_len, ".len", 850842136u, 0, 4, &be_const_str_byte); +be_define_const_str(byte, "byte", 1683620383u, 0, 4, &be_const_str_issubclass); +be_define_const_str(issubclass, "issubclass", 4078395519u, 0, 10, &be_const_str_while); +be_define_const_str(while, "while", 231090382u, 53, 5, NULL); +be_define_const_str(enabled, "enabled", 49525662u, 0, 7, &be_const_str_sin); +be_define_const_str(sin, "sin", 3761252941u, 0, 3, &be_const_str_except); +be_define_const_str(except, "except", 950914032u, 69, 6, NULL); +be_define_const_str(AudioOutputI2S, "AudioOutputI2S", 638031784u, 0, 14, &be_const_str_SERIAL_7N2); +be_define_const_str(SERIAL_7N2, "SERIAL_7N2", 1874282627u, 0, 10, &be_const_str_call); +be_define_const_str(call, "call", 3018949801u, 0, 4, &be_const_str_imax); +be_define_const_str(imax, "imax", 3084515410u, 0, 4, NULL); +be_define_const_str(isrunning, "isrunning", 1688182268u, 0, 9, &be_const_str_read8); +be_define_const_str(read8, "read8", 2802788167u, 0, 5, &be_const_str_resp_cmnd_error); +be_define_const_str(resp_cmnd_error, "resp_cmnd_error", 2404088863u, 0, 15, NULL); +be_define_const_str(AudioFileSourceFS, "AudioFileSourceFS", 1839147653u, 0, 17, &be_const_str___iterator__); +be_define_const_str(__iterator__, "__iterator__", 3884039703u, 0, 12, &be_const_str_contains); +be_define_const_str(contains, "contains", 1825239352u, 0, 8, &be_const_str_web_send_decimal); +be_define_const_str(web_send_decimal, "web_send_decimal", 1407210204u, 0, 16, NULL); +be_define_const_str(dac_voltage, "dac_voltage", 1552257222u, 0, 11, NULL); +be_define_const_str(time_reached, "time_reached", 2075136773u, 0, 12, &be_const_str_if); +be_define_const_str(if, "if", 959999494u, 50, 2, NULL); +be_define_const_str(read24, "read24", 1808533811u, 0, 6, &be_const_str_toptr); +be_define_const_str(toptr, "toptr", 3379847454u, 0, 5, &be_const_str_else); +be_define_const_str(else, "else", 3183434736u, 52, 4, NULL); +be_define_const_str(_global_addr, "_global_addr", 533766721u, 0, 12, &be_const_str_classof); +be_define_const_str(classof, "classof", 1796577762u, 0, 7, NULL); +be_define_const_str(SERIAL_7O1, "SERIAL_7O1", 1823802675u, 0, 10, &be_const_str_print); +be_define_const_str(print, "print", 372738696u, 0, 5, &be_const_str_setmember); +be_define_const_str(setmember, "setmember", 1432909441u, 0, 9, NULL); +be_define_const_str(dot_size, ".size", 1965188224u, 0, 5, &be_const_str__write); +be_define_const_str(_write, "_write", 2215462825u, 0, 6, &be_const_str_init); +be_define_const_str(init, "init", 380752755u, 0, 4, NULL); +be_define_const_str(gamma10, "gamma10", 3472052483u, 0, 7, &be_const_str_gen_cb); +be_define_const_str(gen_cb, "gen_cb", 3245227551u, 0, 6, &be_const_str_remove_rule); +be_define_const_str(remove_rule, "remove_rule", 3456211328u, 0, 11, NULL); +be_define_const_str(ctypes_bytes_dyn, "ctypes_bytes_dyn", 915205307u, 0, 16, NULL); +be_define_const_str(SERIAL_6N2, "SERIAL_6N2", 148562844u, 0, 10, &be_const_str_available); +be_define_const_str(available, "available", 1727918744u, 0, 9, &be_const_str_cb_dispatch); +be_define_const_str(cb_dispatch, "cb_dispatch", 1741510499u, 0, 11, &be_const_str_isinstance); +be_define_const_str(isinstance, "isinstance", 3669352738u, 0, 10, NULL); +be_define_const_str(copy, "copy", 3848464964u, 0, 4, &be_const_str_find); +be_define_const_str(find, "find", 3186656602u, 0, 4, NULL); +be_define_const_str(POST, "POST", 1929554311u, 0, 4, &be_const_str_write_bytes); +be_define_const_str(write_bytes, "write_bytes", 1227543792u, 0, 11, NULL); +be_define_const_str(, "", 2166136261u, 0, 0, &be_const_str_type); +be_define_const_str(type, "type", 1361572173u, 0, 4, NULL); +be_define_const_str(allocated, "allocated", 429986098u, 0, 9, &be_const_str_insert); +be_define_const_str(insert, "insert", 3332609576u, 0, 6, &be_const_str_tolower); +be_define_const_str(tolower, "tolower", 1042520049u, 0, 7, NULL); +be_define_const_str(dot_w, ".w", 1255414514u, 0, 2, &be_const_str_srand); +be_define_const_str(srand, "srand", 465518633u, 0, 5, &be_const_str_wire2); +be_define_const_str(wire2, "wire2", 3229499038u, 0, 5, NULL); +be_define_const_str(format, "format", 3114108242u, 0, 6, &be_const_str_yield); +be_define_const_str(yield, "yield", 1821831854u, 0, 5, NULL); +be_define_const_str(SERIAL_5E2, "SERIAL_5E2", 1180552854u, 0, 10, &be_const_str_reduce); +be_define_const_str(reduce, "reduce", 2002030311u, 0, 6, &be_const_str_resp_cmnd_done); +be_define_const_str(resp_cmnd_done, "resp_cmnd_done", 2601874875u, 0, 14, NULL); +be_define_const_str(abs, "abs", 709362235u, 0, 3, &be_const_str_setitem); +be_define_const_str(setitem, "setitem", 1554834596u, 0, 7, NULL); +be_define_const_str(OneWire, "OneWire", 2298990722u, 0, 7, &be_const_str_upper); +be_define_const_str(upper, "upper", 176974407u, 0, 5, NULL); +be_define_const_str(module, "module", 3617558685u, 0, 6, NULL); +be_define_const_str(counters, "counters", 4095866864u, 0, 8, &be_const_str_tag); +be_define_const_str(tag, "tag", 2516003219u, 0, 3, NULL); +be_define_const_str(tanh, "tanh", 153638352u, 0, 4, NULL); +be_define_const_str(get_string, "get_string", 4195847969u, 0, 10, &be_const_str_read12); +be_define_const_str(read12, "read12", 4291076970u, 0, 6, &be_const_str_wire_scan); +be_define_const_str(wire_scan, "wire_scan", 2671275880u, 0, 9, NULL); +be_define_const_str(seti, "seti", 1500556254u, 0, 4, NULL); +be_define_const_str(cmd, "cmd", 4136785899u, 0, 3, &be_const_str_content_send); +be_define_const_str(content_send, "content_send", 1673733649u, 0, 12, &be_const_str_global); +be_define_const_str(global, "global", 503252654u, 0, 6, &be_const_str_var); +be_define_const_str(var, "var", 2317739966u, 64, 3, NULL); +be_define_const_str(SERIAL_7N1, "SERIAL_7N1", 1891060246u, 0, 10, &be_const_str_resize); +be_define_const_str(resize, "resize", 3514612129u, 0, 6, &be_const_str_split); +be_define_const_str(split, "split", 2276994531u, 0, 5, &be_const_str_str); +be_define_const_str(str, "str", 3259748752u, 0, 3, &be_const_str_url_encode); +be_define_const_str(url_encode, "url_encode", 528392145u, 0, 10, NULL); +be_define_const_str(get_option, "get_option", 2123730033u, 0, 10, &be_const_str_listdir); +be_define_const_str(listdir, "listdir", 2005220720u, 0, 7, &be_const_str_tomap); +be_define_const_str(tomap, "tomap", 612167626u, 0, 5, NULL); +be_define_const_str(check_privileged_access, "check_privileged_access", 3692933968u, 0, 23, NULL); +be_define_const_str(pin_mode, "pin_mode", 3258314030u, 0, 8, NULL); +be_define_const_str(pin, "pin", 1866532500u, 0, 3, &be_const_str_try); +be_define_const_str(try, "try", 2887626766u, 68, 3, NULL); +be_define_const_str(_buffer, "_buffer", 2044888568u, 0, 7, &be_const_str_cos); +be_define_const_str(cos, "cos", 4220379804u, 0, 3, NULL); +be_define_const_str(dot_p, ".p", 1171526419u, 0, 2, &be_const_str_SERIAL_7O2); +be_define_const_str(SERIAL_7O2, "SERIAL_7O2", 1840580294u, 0, 10, NULL); +be_define_const_str(real, "real", 3604983901u, 0, 4, NULL); +be_define_const_str(set_timer, "set_timer", 2135414533u, 0, 9, NULL); +be_define_const_str(count, "count", 967958004u, 0, 5, &be_const_str_write); +be_define_const_str(write, "write", 3190202204u, 0, 5, NULL); +be_define_const_str(_settings_def, "_settings_def", 3775560307u, 0, 13, &be_const_str_digital_read); +be_define_const_str(digital_read, "digital_read", 3585496928u, 0, 12, NULL); +be_define_const_str(path, "path", 2223459638u, 0, 4, NULL); +be_define_const_str(delay, "delay", 1322381784u, 0, 5, &be_const_str_stop); +be_define_const_str(stop, "stop", 3411225317u, 0, 4, NULL); +be_define_const_str(AES_GCM, "AES_GCM", 3832208678u, 0, 7, NULL); +be_define_const_str(SERIAL_6O2, "SERIAL_6O2", 316486129u, 0, 10, &be_const_str_open); +be_define_const_str(open, "open", 3546203337u, 0, 4, &be_const_str_top); +be_define_const_str(top, "top", 2802900028u, 0, 3, NULL); +be_define_const_str(write_bit, "write_bit", 2660990436u, 0, 9, NULL); +be_define_const_str(state, "state", 2016490230u, 0, 5, NULL); +be_define_const_str(set_useragent, "set_useragent", 612237244u, 0, 13, &be_const_str_as); +be_define_const_str(as, "as", 1579491469u, 67, 2, NULL); +be_define_const_str(erase, "erase", 1010949589u, 0, 5, &be_const_str_has_arg); +be_define_const_str(has_arg, "has_arg", 424878688u, 0, 7, &be_const_str_map); +be_define_const_str(map, "map", 3751997361u, 0, 3, &be_const_str_on); +be_define_const_str(on, "on", 1630810064u, 0, 2, NULL); +be_define_const_str(AudioGeneratorWAV, "AudioGeneratorWAV", 2746509368u, 0, 17, &be_const_str__cb); +be_define_const_str(_cb, "_cb", 4043300367u, 0, 3, &be_const_str_decrypt); +be_define_const_str(decrypt, "decrypt", 2886974618u, 0, 7, &be_const_str_sqrt); +be_define_const_str(sqrt, "sqrt", 2112764879u, 0, 4, NULL); +be_define_const_str(SERIAL_5N1, "SERIAL_5N1", 3313031680u, 0, 10, NULL); +be_define_const_str(find_key_i, "find_key_i", 850136726u, 0, 10, NULL); +be_define_const_str(arg, "arg", 1047474471u, 0, 3, &be_const_str_depower); +be_define_const_str(depower, "depower", 3563819571u, 0, 7, &be_const_str_write_file); +be_define_const_str(write_file, "write_file", 3177658879u, 0, 10, NULL); +be_define_const_str(SERIAL_5O2, "SERIAL_5O2", 3732325060u, 0, 10, &be_const_str_get_light); +be_define_const_str(get_light, "get_light", 381930476u, 0, 9, &be_const_str_pop); +be_define_const_str(pop, "pop", 1362321360u, 0, 3, NULL); +be_define_const_str(exec_tele, "exec_tele", 1020751601u, 0, 9, NULL); +be_define_const_str(set_light, "set_light", 3176076152u, 0, 9, &be_const_str_set_timeouts); +be_define_const_str(set_timeouts, "set_timeouts", 3732850900u, 0, 12, &be_const_str_sinh); +be_define_const_str(sinh, "sinh", 282220607u, 0, 4, NULL); +be_define_const_str(AudioGenerator, "AudioGenerator", 1839297342u, 0, 14, &be_const_str_SERIAL_7E1); +be_define_const_str(SERIAL_7E1, "SERIAL_7E1", 147718061u, 0, 10, &be_const_str_getbits); +be_define_const_str(getbits, "getbits", 3094168979u, 0, 7, &be_const_str_shared_key); +be_define_const_str(shared_key, "shared_key", 2200833624u, 0, 10, &be_const_str_time_dump); +be_define_const_str(time_dump, "time_dump", 3330410747u, 0, 9, NULL); +be_define_const_str(content_button, "content_button", 1956476087u, 0, 14, &be_const_str_geti); +be_define_const_str(geti, "geti", 2381006490u, 0, 4, NULL); +be_define_const_str(arch, "arch", 2952804297u, 0, 4, &be_const_str_asin); +be_define_const_str(asin, "asin", 4272848550u, 0, 4, &be_const_str_get_free_heap); +be_define_const_str(get_free_heap, "get_free_heap", 625069757u, 0, 13, &be_const_str_resp_cmnd); +be_define_const_str(resp_cmnd, "resp_cmnd", 2869459626u, 0, 9, NULL); +be_define_const_str(content_flush, "content_flush", 214922475u, 0, 13, &be_const_str_millis); +be_define_const_str(millis, "millis", 1214679063u, 0, 6, &be_const_str_serial); +be_define_const_str(serial, "serial", 3687697785u, 0, 6, &be_const_str_skip); +be_define_const_str(skip, "skip", 1097563074u, 0, 4, NULL); +be_define_const_str(event, "event", 4264611999u, 0, 5, NULL); +be_define_const_str(opt_add, "+", 772578730u, 0, 1, &be_const_str_bus); +be_define_const_str(bus, "bus", 1607822841u, 0, 3, NULL); +be_define_const_str(acos, "acos", 1006755615u, 0, 4, &be_const_str_bytes); +be_define_const_str(bytes, "bytes", 1706151940u, 0, 5, &be_const_str_compile); +be_define_const_str(compile, "compile", 1000265118u, 0, 7, &be_const_str_get); +be_define_const_str(get, "get", 1410115415u, 0, 3, &be_const_str_tan); +be_define_const_str(tan, "tan", 2633446552u, 0, 3, NULL); +be_define_const_str(encrypt, "encrypt", 2194327650u, 0, 7, NULL); +be_define_const_str(cmd_res, "cmd_res", 921166762u, 0, 7, &be_const_str_collect); +be_define_const_str(collect, "collect", 2399039025u, 0, 7, NULL); +be_define_const_str(arg_size, "arg_size", 3310243257u, 0, 8, &be_const_str_reverse); +be_define_const_str(reverse, "reverse", 558918661u, 0, 7, NULL); +be_define_const_str(close, "close", 667630371u, 0, 5, &be_const_str_members); +be_define_const_str(members, "members", 937576464u, 0, 7, NULL); +be_define_const_str(assert, "assert", 2774883451u, 0, 6, &be_const_str_exec_cmd); +be_define_const_str(exec_cmd, "exec_cmd", 493567399u, 0, 8, &be_const_str_get_power); +be_define_const_str(get_power, "get_power", 3009799377u, 0, 9, &be_const_str_resp_cmnd_failed); +be_define_const_str(resp_cmnd_failed, "resp_cmnd_failed", 2136281562u, 0, 16, &be_const_str_target_search); +be_define_const_str(target_search, "target_search", 1947846553u, 0, 13, NULL); +be_define_const_str(AudioFileSource, "AudioFileSource", 2959980058u, 0, 15, &be_const_str_SERIAL_8N1); +be_define_const_str(SERIAL_8N1, "SERIAL_8N1", 2369297235u, 0, 10, &be_const_str_pi); +be_define_const_str(pi, "pi", 1213090802u, 0, 2, NULL); +be_define_const_str(add_header, "add_header", 927130612u, 0, 10, &be_const_str_list); +be_define_const_str(list, "list", 217798785u, 0, 4, &be_const_str_super); +be_define_const_str(super, "super", 4152230356u, 0, 5, NULL); +be_define_const_str(has, "has", 3988721635u, 0, 3, NULL); +be_define_const_str(__upper__, "__upper__", 3612202883u, 0, 9, &be_const_str_exp); +be_define_const_str(exp, "exp", 1923516200u, 0, 3, &be_const_str_int); +be_define_const_str(int, "int", 2515107422u, 0, 3, &be_const_str_size); +be_define_const_str(size, "size", 597743964u, 0, 4, &be_const_str_for); +be_define_const_str(for, "for", 2901640080u, 54, 3, NULL); +be_define_const_str(ctypes_bytes, "ctypes_bytes", 3879019703u, 0, 12, &be_const_str_wifi); +be_define_const_str(wifi, "wifi", 120087624u, 0, 4, &be_const_str_elif); +be_define_const_str(elif, "elif", 3232090307u, 51, 4, NULL); +be_define_const_str(arg_name, "arg_name", 1345046155u, 0, 8, &be_const_str_cosh); +be_define_const_str(cosh, "cosh", 4099687964u, 0, 4, &be_const_str_lower); +be_define_const_str(lower, "lower", 3038577850u, 0, 5, &be_const_str_push); +be_define_const_str(push, "push", 2272264157u, 0, 4, &be_const_str_save); +be_define_const_str(save, "save", 3439296072u, 0, 4, NULL); +be_define_const_str(load, "load", 3859241449u, 0, 4, NULL); +be_define_const_str(SERIAL_8E2, "SERIAL_8E2", 2421454473u, 0, 10, &be_const_str_nan); +be_define_const_str(nan, "nan", 797905850u, 0, 3, &be_const_str_remove_driver); +be_define_const_str(remove_driver, "remove_driver", 1030243768u, 0, 13, &be_const_str_write8); +be_define_const_str(write8, "write8", 3133991532u, 0, 6, NULL); +be_define_const_str(_get_cb, "_get_cb", 1448849122u, 0, 7, NULL); +be_define_const_str(iter, "iter", 3124256359u, 0, 4, NULL); +be_define_const_str(_cmd, "_cmd", 3419822142u, 0, 4, &be_const_str_exists); +be_define_const_str(exists, "exists", 1002329533u, 0, 6, NULL); +be_define_const_str(AudioGeneratorMP3, "AudioGeneratorMP3", 2199818488u, 0, 17, &be_const_str__end_transmission); +be_define_const_str(_end_transmission, "_end_transmission", 3237480400u, 0, 17, NULL); +be_define_const_str(get_switch, "get_switch", 164821028u, 0, 10, NULL); +be_define_const_str(_available, "_available", 1306196581u, 0, 10, NULL); +be_define_const_str(false, "false", 184981848u, 62, 5, NULL); +be_define_const_str(settings, "settings", 1745255176u, 0, 8, &be_const_str_wd); +be_define_const_str(wd, "wd", 1531424278u, 0, 2, NULL); +be_define_const_str(SERIAL_8O2, "SERIAL_8O2", 272345123u, 0, 10, &be_const_str_rad); +be_define_const_str(rad, "rad", 1358899048u, 0, 3, NULL); +be_define_const_str(kv, "kv", 1497177492u, 0, 2, &be_const_str_toupper); +be_define_const_str(toupper, "toupper", 3691983576u, 0, 7, &be_const_str_tr); +be_define_const_str(tr, "tr", 1195724803u, 0, 2, &be_const_str_return); +be_define_const_str(return, "return", 2246981567u, 60, 6, NULL); +be_define_const_str(memory, "memory", 2229924270u, 0, 6, &be_const_str_tostring); +be_define_const_str(tostring, "tostring", 2299708645u, 0, 8, NULL); static const bstring* const m_string_table[] = { - NULL, - (const bstring *)&be_const_str_setmember, - (const bstring *)&be_const_str_hex, - (const bstring *)&be_const_str_arch, - (const bstring *)&be_const_str_top, - (const bstring *)&be_const_str_content_start, - (const bstring *)&be_const_str_compile, - (const bstring *)&be_const_str_arg_name, - (const bstring *)&be_const_str_insert, - (const bstring *)&be_const_str_open, - NULL, - (const bstring *)&be_const_str_ctypes_bytes, - (const bstring *)&be_const_str_reset, - (const bstring *)&be_const_str_POST, - (const bstring *)&be_const_str_available, - NULL, - (const bstring *)&be_const_str__get_cb, - (const bstring *)&be_const_str_get_string, - (const bstring *)&be_const_str_asstring, - (const bstring *)&be_const_str_static, - (const bstring *)&be_const_str_AES_GCM, - (const bstring *)&be_const_str_close, - (const bstring *)&be_const_str_find_op, - (const bstring *)&be_const_str_get, - (const bstring *)&be_const_str_print, - (const bstring *)&be_const_str_target_search, - NULL, - (const bstring *)&be_const_str__ccmd, - (const bstring *)&be_const_str_allocated, - (const bstring *)&be_const_str_GET, - (const bstring *)&be_const_str_SERIAL_8E1, - (const bstring *)&be_const_str_assert, - (const bstring *)&be_const_str_codedump, - (const bstring *)&be_const_str_opt_connect, - (const bstring *)&be_const_str_update, - NULL, - (const bstring *)&be_const_str__cmd, - (const bstring *)&be_const_str_SERIAL_5O1, - (const bstring *)&be_const_str_SERIAL_7E2, - (const bstring *)&be_const_str_SERIAL_6N1, - (const bstring *)&be_const_str_Tasmota, - (const bstring *)&be_const_str_time_reached, - (const bstring *)&be_const_str_chars_in_string, - (const bstring *)&be_const_str_add_rule, - NULL, - (const bstring *)&be_const_str_hs2rgb, - (const bstring *)&be_const_str_SERIAL_8O1, - (const bstring *)&be_const_str_AudioFileSourceFS, - (const bstring *)&be_const_str_AudioGenerator, - (const bstring *)&be_const_str__global_addr, - (const bstring *)&be_const_str_dot_w, + (const bstring *)&be_const_str_pow, (const bstring *)&be_const_str_MD5, - (const bstring *)&be_const_str_break, - (const bstring *)&be_const_str_digital_write, - (const bstring *)&be_const_str_asin, - (const bstring *)&be_const_str__def, - (const bstring *)&be_const_str_set_light, - (const bstring *)&be_const_str_arg_size, + (const bstring *)&be_const_str_dot_p2, + (const bstring *)&be_const_str_atan, + (const bstring *)&be_const_str_SERIAL_6N1, + (const bstring *)&be_const_str_content_start, + (const bstring *)&be_const_str_SERIAL_8N2, + (const bstring *)&be_const_str_content_send_style, NULL, - (const bstring *)&be_const_str_opt_eq, - (const bstring *)&be_const_str_kv, - (const bstring *)&be_const_str_tostring, - (const bstring *)&be_const_str_format, - (const bstring *)&be_const_str_log, - (const bstring *)&be_const_str_SERIAL_7N1, - (const bstring *)&be_const_str_stop, - (const bstring *)&be_const_str_count, - (const bstring *)&be_const_str_byte, - (const bstring *)&be_const_str_fromstring, - (const bstring *)&be_const_str_cmd, - (const bstring *)&be_const_str_SERIAL_6E1, + (const bstring *)&be_const_str__begin_transmission, + (const bstring *)&be_const_str_number, + (const bstring *)&be_const_str_exec_rules, + (const bstring *)&be_const_str_GET, + (const bstring *)&be_const_str_I2C_Driver, + NULL, + (const bstring *)&be_const_str_opt_neq, + (const bstring *)&be_const_str_last_modified, + (const bstring *)&be_const_str_add, + (const bstring *)&be_const_str_rtc, (const bstring *)&be_const_str_EC_C25519, - (const bstring *)&be_const_str_read12, - (const bstring *)&be_const_str__write, + (const bstring *)&be_const_str_ceil, + (const bstring *)&be_const_str_log, + (const bstring *)&be_const_str__global_def, + (const bstring *)&be_const_str_atan2, + (const bstring *)&be_const_str_deinit, + (const bstring *)&be_const_str_SERIAL_8O1, + (const bstring *)&be_const_str_SERIAL_6O1, + (const bstring *)&be_const_str_SERIAL_6E2, + (const bstring *)&be_const_str_gc, + (const bstring *)&be_const_str_continue, + NULL, + (const bstring *)&be_const_str_dot_p1, + (const bstring *)&be_const_str_chars_in_string, + NULL, + (const bstring *)&be_const_str_traceback, + (const bstring *)&be_const_str_calldepth, + (const bstring *)&be_const_str_finish, + (const bstring *)&be_const_str_read, + (const bstring *)&be_const_str_Tasmota, + (const bstring *)&be_const_str_SERIAL_7E2, + (const bstring *)&be_const_str___lower__, + (const bstring *)&be_const_str_member, + (const bstring *)&be_const_str_codedump, (const bstring *)&be_const_str_opt_call, NULL, - (const bstring *)&be_const_str_AudioGeneratorMP3, - (const bstring *)&be_const_str_ctypes_bytes_dyn, - (const bstring *)&be_const_str_set_auth, - (const bstring *)&be_const_str_, + (const bstring *)&be_const_str_attrdump, + (const bstring *)&be_const_str_AudioOutput, + (const bstring *)&be_const_str_SERIAL_5O1, (const bstring *)&be_const_str_public_key, - (const bstring *)&be_const_str_get_power, - (const bstring *)&be_const_str_opt_add, - (const bstring *)&be_const_str_getbits, - (const bstring *)&be_const_str_dot_p1, - (const bstring *)&be_const_str_read8, - (const bstring *)&be_const_str_AudioGeneratorWAV, - (const bstring *)&be_const_str__global_def, - (const bstring *)&be_const_str__ptr, - NULL, - (const bstring *)&be_const_str_pin, - (const bstring *)&be_const_str_dot_p, - (const bstring *)&be_const_str_I2C_Driver, - (const bstring *)&be_const_str_SERIAL_8N1, - (const bstring *)&be_const_str_SERIAL_5O2, - (const bstring *)&be_const_str_last_modified, - (const bstring *)&be_const_str_SERIAL_6N2, - (const bstring *)&be_const_str_call, - (const bstring *)&be_const_str_escape, - (const bstring *)&be_const_str_upper, - (const bstring *)&be_const_str_end, - NULL, - (const bstring *)&be_const_str_gamma8, - NULL, - (const bstring *)&be_const_str_yield, - (const bstring *)&be_const_str_get_option, - (const bstring *)&be_const_str__settings_ptr, - (const bstring *)&be_const_str___upper__, - (const bstring *)&be_const_str_save, - NULL, - (const bstring *)&be_const_str___lower__, - NULL, - (const bstring *)&be_const_str_check_privileged_access, (const bstring *)&be_const_str_i2c_enabled, - (const bstring *)&be_const_str_dac_voltage, - (const bstring *)&be_const_str_resp_cmnd_error, - (const bstring *)&be_const_str_calldepth, - (const bstring *)&be_const_str___iterator__, - (const bstring *)&be_const_str_rad, - (const bstring *)&be_const_str_SERIAL_8O2, - (const bstring *)&be_const_str_resp_cmnd, - (const bstring *)&be_const_str_SERIAL_5E1, - (const bstring *)&be_const_str_OneWire, - NULL, - (const bstring *)&be_const_str_add, - (const bstring *)&be_const_str_gc, - NULL, - (const bstring *)&be_const_str_content_stop, - (const bstring *)&be_const_str_counters, - (const bstring *)&be_const_str_arg, - (const bstring *)&be_const_str_AudioOutputI2S, - (const bstring *)&be_const_str_cb_dispatch, - (const bstring *)&be_const_str_write_bytes, - (const bstring *)&be_const_str__settings_def, - (const bstring *)&be_const_str_cosh, - (const bstring *)&be_const_str_SERIAL_8E2, - (const bstring *)&be_const_str_AudioFileSource, - (const bstring *)&be_const_str_SERIAL_7N2, - (const bstring *)&be_const_str_exec_rules, - (const bstring *)&be_const_str__available, - (const bstring *)&be_const_str_global, - (const bstring *)&be_const_str_collect, - (const bstring *)&be_const_str_str, - (const bstring *)&be_const_str_SERIAL_6E2, - (const bstring *)&be_const_str_number, + (const bstring *)&be_const_str_fromptr, + (const bstring *)&be_const_str__drivers, + (const bstring *)&be_const_str_loop, (const bstring *)&be_const_str_add_cmd, + (const bstring *)&be_const_str__settings_ptr, + (const bstring *)&be_const_str__ptr, + (const bstring *)&be_const_str_SERIAL_6E1, + (const bstring *)&be_const_str_true, + (const bstring *)&be_const_str_opt_eq, + (const bstring *)&be_const_str__timers, + (const bstring *)&be_const_str_opt_connect, + (const bstring *)&be_const_str_deg, + (const bstring *)&be_const_str_SERIAL_8E1, NULL, - (const bstring *)&be_const_str_atan2, - (const bstring *)&be_const_str__end_transmission, NULL, - (const bstring *)&be_const_str_geti, NULL, - (const bstring *)&be_const_str__buffer, - (const bstring *)&be_const_str_atan, (const bstring *)&be_const_str_dot_len, - (const bstring *)&be_const_str_pow, + NULL, (const bstring *)&be_const_str_enabled, - (const bstring *)&be_const_str_opt_neq, - (const bstring *)&be_const_str_Wire, - (const bstring *)&be_const_str_floor, - (const bstring *)&be_const_str_classname, - (const bstring *)&be_const_str_add_driver + (const bstring *)&be_const_str_AudioOutputI2S, + (const bstring *)&be_const_str_isrunning, + (const bstring *)&be_const_str_AudioFileSourceFS, + (const bstring *)&be_const_str_dac_voltage, + (const bstring *)&be_const_str_time_reached, + (const bstring *)&be_const_str_read24, + (const bstring *)&be_const_str__global_addr, + (const bstring *)&be_const_str_SERIAL_7O1, + (const bstring *)&be_const_str_dot_size, + (const bstring *)&be_const_str_gamma10, + (const bstring *)&be_const_str_ctypes_bytes_dyn, + (const bstring *)&be_const_str_SERIAL_6N2, + NULL, + (const bstring *)&be_const_str_copy, + (const bstring *)&be_const_str_POST, + (const bstring *)&be_const_str_, + (const bstring *)&be_const_str_allocated, + NULL, + (const bstring *)&be_const_str_dot_w, + (const bstring *)&be_const_str_format, + (const bstring *)&be_const_str_SERIAL_5E2, + (const bstring *)&be_const_str_abs, + (const bstring *)&be_const_str_OneWire, + (const bstring *)&be_const_str_module, + (const bstring *)&be_const_str_counters, + (const bstring *)&be_const_str_tanh, + (const bstring *)&be_const_str_get_string, + (const bstring *)&be_const_str_seti, + (const bstring *)&be_const_str_cmd, + (const bstring *)&be_const_str_SERIAL_7N1, + (const bstring *)&be_const_str_get_option, + (const bstring *)&be_const_str_check_privileged_access, + NULL, + (const bstring *)&be_const_str_pin_mode, + (const bstring *)&be_const_str_pin, + (const bstring *)&be_const_str__buffer, + (const bstring *)&be_const_str_dot_p, + (const bstring *)&be_const_str_real, + (const bstring *)&be_const_str_set_timer, + (const bstring *)&be_const_str_count, + (const bstring *)&be_const_str__settings_def, + (const bstring *)&be_const_str_path, + (const bstring *)&be_const_str_delay, + (const bstring *)&be_const_str_AES_GCM, + (const bstring *)&be_const_str_SERIAL_6O2, + (const bstring *)&be_const_str_write_bit, + (const bstring *)&be_const_str_state, + (const bstring *)&be_const_str_set_useragent, + (const bstring *)&be_const_str_erase, + (const bstring *)&be_const_str_AudioGeneratorWAV, + (const bstring *)&be_const_str_SERIAL_5N1, + (const bstring *)&be_const_str_find_key_i, + NULL, + (const bstring *)&be_const_str_arg, + (const bstring *)&be_const_str_SERIAL_5O2, + (const bstring *)&be_const_str_exec_tele, + (const bstring *)&be_const_str_set_light, + (const bstring *)&be_const_str_AudioGenerator, + (const bstring *)&be_const_str_content_button, + (const bstring *)&be_const_str_arch, + (const bstring *)&be_const_str_content_flush, + (const bstring *)&be_const_str_event, + NULL, + (const bstring *)&be_const_str_opt_add, + (const bstring *)&be_const_str_acos, + (const bstring *)&be_const_str_encrypt, + (const bstring *)&be_const_str_cmd_res, + NULL, + (const bstring *)&be_const_str_arg_size, + (const bstring *)&be_const_str_close, + (const bstring *)&be_const_str_assert, + (const bstring *)&be_const_str_AudioFileSource, + (const bstring *)&be_const_str_add_header, + NULL, + (const bstring *)&be_const_str_has, + (const bstring *)&be_const_str___upper__, + (const bstring *)&be_const_str_ctypes_bytes, + NULL, + (const bstring *)&be_const_str_arg_name, + (const bstring *)&be_const_str_load, + (const bstring *)&be_const_str_SERIAL_8E2, + (const bstring *)&be_const_str__get_cb, + (const bstring *)&be_const_str_iter, + NULL, + (const bstring *)&be_const_str__cmd, + (const bstring *)&be_const_str_AudioGeneratorMP3, + (const bstring *)&be_const_str_get_switch, + (const bstring *)&be_const_str__available, + (const bstring *)&be_const_str_false, + (const bstring *)&be_const_str_settings, + (const bstring *)&be_const_str_SERIAL_8O2, + NULL, + (const bstring *)&be_const_str_kv, + (const bstring *)&be_const_str_memory }; static const struct bconststrtab m_const_string_table = { - .size = 162, - .count = 325, + .size = 163, + .count = 326, .table = m_string_table }; diff --git a/lib/libesp32/Berry/generate/be_fixed_sys.h b/lib/libesp32/Berry/generate/be_fixed_sys.h index 12eff88ab..91403719c 100644 --- a/lib/libesp32/Berry/generate/be_fixed_sys.h +++ b/lib/libesp32/Berry/generate/be_fixed_sys.h @@ -1,2 +1,17 @@ #include "be_constobj.h" +static be_define_const_map_slots(m_libsys_map) { + { be_const_key(path, -1), be_const_func(m_path) }, +}; + +static be_define_const_map( + m_libsys_map, + 1 +); + +static be_define_const_module( + m_libsys, + "sys" +); + +BE_EXPORT_VARIABLE be_define_const_native_module(sys); diff --git a/lib/libesp32/Zip-readonly-FS/src/ZipReadFS.cpp b/lib/libesp32/Zip-readonly-FS/src/ZipReadFS.cpp index 61e83b683..2f036ad8c 100644 --- a/lib/libesp32/Zip-readonly-FS/src/ZipReadFS.cpp +++ b/lib/libesp32/Zip-readonly-FS/src/ZipReadFS.cpp @@ -400,6 +400,8 @@ FileImplPtr ZipReadFSImpl::open(const char* path, const char* mode, const bool c char *tok; char *prefix = strtok_r(sub_path, "#", &tok); char *suffix = strtok_r(NULL, "", &tok); + // if suffix starts with '/', skip the first char + if (*suffix == '/') { suffix++; } AddLog(LOG_LEVEL_DEBUG, "ZIP: prefix=%s suffix=%s", prefix, suffix); // parse ZIP archive File zipfile = (*_fs)->open(prefix, "r", false); From fb41a57ae2ddbe6f81cf8373a3cfe1df84702ce0 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 20 Nov 2021 12:07:11 +0100 Subject: [PATCH 068/185] Delete scrape_supported_devices.py --- .../tools/scrape_supported_devices.py | 426 ------------------ 1 file changed, 426 deletions(-) delete mode 100755 lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/scrape_supported_devices.py diff --git a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/scrape_supported_devices.py b/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/scrape_supported_devices.py deleted file mode 100755 index f40b3e959..000000000 --- a/lib/lib_basic/IRremoteESP8266/IRremoteESP8266/tools/scrape_supported_devices.py +++ /dev/null @@ -1,426 +0,0 @@ -#!/usr/bin/env python3 -"""Generate SupportedProtocols.md by scraping source code files""" -import pathlib -import argparse -import subprocess -from io import StringIO -import sys -import re -import time - -CODE_URL = "https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_" - -BRAND_MODEL = re.compile(r""" - Brand:\s{1,20} # "Brand:" label followd by between 1 and 20 whitespace chars. - \b(?P.{1,40})\b # The actual brand of the device, max 40 chars. - \s{0,10}, # Followed by at most 10 whitespace chars, then a comma. - \s{1,20} # The between 1 and 20 whitespace chars. - Model:\s{1,20} # "Model:" label followd by between 1 and 20 whitespace chars. - \b(?P.{1,80}) # The model info of the device, max 80 chars. - \s{0,5}$ # Followed by at most 5 whitespaces before the end of line. - """, re.VERBOSE) -ENUMS = re.compile(r"enum (\w{1,60}) {(.{1,5000}?)};", re.DOTALL) -ENUM_ENTRY = re.compile(r"^\s{1,80}(\w{1,80})", re.MULTILINE) -DECODED_PROTOCOLS = re.compile(r""" - .{0,80} # Ignore upto an 80 char line of whitespace/code etc. - # Now look for code that looks like we are assigning the Protocol type. - # There are two typical styles used: - (?:results->decode_type # The first style. - | # Or - typeguess) # The second style - \s{0,5}=\s{0,5} # The assignment operator and potential whitespace - (?:decode_type_t::)? # The protocol could have an optional type prefix. - (\w{1,40}); # Finally, the last word of code should be the Protocol. - """, re.VERBOSE) -AC_FN = re.compile(r"ir_(.{1,80})\.h") -AC_MODEL_ENUM_RE = re.compile(r"(.{1,40})_ac_remote_model_t") -IRSEND_FN_RE = re.compile(r"IRsend\.h") -ALL_FN = re.compile(r"ir_(.{1,80})\.(h|cpp)") - -EXCLUDED_PROTOCOLS = ["UNKNOWN", "UNUSED", "kLastDecodeType", "typeguess"] -EXCLUDED_ACS = ["Magiquest", "NEC"] - -def getgitcommittime(): - """Call git to get time of last commit - """ - try: - label = subprocess.check_output(\ - ["git", "show", "-s", "--format=%ct", "HEAD"]).strip() - return int(label) - except FileNotFoundError as err: - print("Git failed, which is ok, no git binary found?:", err) - return None - except subprocess.SubprocessError as err: - print("Git failed, which is ok, see output, maybe no git checkout?:", err) - return None - -def getmarkdownheader(): - """Get the generated header - """ - srctime = getgitcommittime() - # pylint: disable=C0209 - return """""".format( - time.strftime("%a %d %b %Y %H:%M:%S +0000", time.gmtime(srctime))) - # pylint: enable=C0209 - - - -def getallprotocols(): - """Return all protocls configured in IRremoteESP8266.h - """ - irremote = ARGS.directory / "IRremoteESP8266.h" - enums = getenums(irremote)["decode_type_t"] - if not enums: - errorexit("Error getting ENUMS from IRremoteESP8266.h") - return enums - - -def getdecodedprotocols(): - """All protocols that include decoding support""" - ret = set() - for path in ARGS.directory.iterdir(): - if path.suffix != ".cpp": - continue - matches = DECODED_PROTOCOLS.finditer(path.open(encoding="utf-8").read()) - for match in matches: - protocol = match.group(1) - if protocol not in EXCLUDED_PROTOCOLS: - ret.add(protocol) - return ret - - -def getallacs(): - """All supported A/C codes""" - ret = {} - for path in ARGS.directory.iterdir(): - match = AC_FN.match(path.name) - if match: - acprotocol = match.group(1) - rawmodels = getenums(path) - models = set() - for model in rawmodels: - model = model.upper() - model = model.replace(f"K{acprotocol.upper()}", "") - if model and model not in EXCLUDED_PROTOCOLS: - models.add(model) - if acprotocol in ret: - ret[acprotocol].update(models) - else: - ret[acprotocol] = models - # Parse IRsend.h's enums - match = IRSEND_FN_RE.match(path.name) - if match: - rawmodels = getenums(path) - for acprotocol, acmodels in rawmodels.items(): - models = set() - for model in acmodels: - model = model.upper() - model = model.replace(f"K{acprotocol.upper()}", "") - if model and model not in EXCLUDED_PROTOCOLS: - models.add(model) - if acprotocol in ret: - ret[acprotocol].update(models) - else: - ret[acprotocol] = models - return ret - -class FnSets(): - """Container for getalldevices""" - def __init__(self): - self.allcodes = {} - self.fnnomatch = set() - self.allhfileprotos = set() - self.fnhmatch = set() - self.fncppmatch = set() - - def add(self, supports, path): - """add the path to correct set based on supports""" - if path.suffix == ".h": - self.allhfileprotos.add(path.stem) - if supports: - if path.suffix == ".h": - self.fnhmatch.add(path.stem) - elif path.suffix == ".cpp": - self.fncppmatch.add(path.stem) - else: - self.fnnomatch.add(path.stem) - - def printwarnings(self): - """print warnings""" - # all protos with support in .cpp file, when there is a .h file - # meaning that the documentation should probably be moved to .h - # in the future, with doxygen, that might change - protosincppwithh = list(self.fncppmatch & self.allhfileprotos) - if protosincppwithh: - protosincppwithh.sort() - print("The following files has supports section in .cpp, expected in .h") - for path in protosincppwithh: - print(f"\t{path}") - - protosincppandh = list(self.fncppmatch & self.fnhmatch) - if protosincppandh: - protosincppandh.sort() - print("The following files has supports section in both .h and .cpp") - for path in protosincppandh: - print(f"\t{path}") - - nosupports = self.getnosupports() - if nosupports: - nosupports.sort() - print("The following files had no supports section:") - for path in nosupports: - print(f"\t{path}") - - return protosincppwithh or protosincppandh or nosupports - - def getnosupports(self): - """get protos without supports sections""" - return list(self.fnnomatch - self.fnhmatch - self.fncppmatch) - - -def getalldevices(): - """All devices and associated branding and model information (if available) - """ - sets = FnSets() - for path in ARGS.directory.iterdir(): - match = ALL_FN.match(path.name) - if not match: - continue - supports = extractsupports(path) - sets.add(supports, path) - protocol = match.group(1) - for brand, model in supports: - protocolbrand = (protocol, brand) - pbset = sets.allcodes.get(protocolbrand, []) - if model in pbset: - print(f"Model {model} is duplicated for {protocol}, {brand}") - sets.allcodes[protocolbrand] = pbset + [model] - - for fnprotocol in sets.getnosupports(): - sets.allcodes[(fnprotocol[3:], "Unknown")] = [] - return sets - - -def getenums(path): - """Returns the keys for the first enum type in path - """ - ret = {} - for enums in ENUMS.finditer(path.open(encoding="utf-8").read()): - if enums: - enum_name = AC_MODEL_ENUM_RE.search(enums.group(1)) - if enum_name: - enum_name = enum_name.group(1).capitalize() - else: - enum_name = enums.group(1) - ret[enum_name] = set() - for enum in ENUM_ENTRY.finditer(enums.group(2)): - enum = enum.group(1) - if enum in EXCLUDED_PROTOCOLS: - continue - ret[enum_name].add(enum) - return ret - - -ARGS = None - - -def initargs(): - """Init the command line arguments""" - global ARGS # pylint: disable=global-statement - parser = argparse.ArgumentParser() - parser.add_argument( - "-n", - "--noout", - help="generate no output data, combine with --alert to only check", - action="store_true", - ) - parser.add_argument( - "-s", - "--stdout", - help="output to stdout rather than SupportedProtocols.md", - action="store_true", - ) - parser.add_argument("-v", - "--verbose", - help="increase output verbosity", - action="store_true") - parser.add_argument( - "-a", - "--alert", - help="alert if a file does not have a supports section, " - "non zero exit code if issues where found", - action="store_true", - ) - parser.add_argument( - "directory", - nargs="?", - help="directory of the source git checkout", - default=None, - ) - ARGS = parser.parse_args() - if ARGS.directory is None: - src = pathlib.Path("../src") - if not src.is_dir(): - src = pathlib.Path("./src") - else: - src = pathlib.Path(ARGS.directory) / "src" - if not src.is_dir(): - errorexit(f"Directory not valid: {src!s}") - ARGS.directory = src - return ARGS - -def getmdfile(): - """Resolves SupportedProtocols.md path""" - foutpath = ARGS.directory / "../SupportedProtocols.md" - return foutpath.resolve() - -def errorexit(msg): - """Print an error and exit on critical error""" - sys.stderr.write(f"{msg}\n") - sys.exit(1) - -def extractsupports(path): - """Extract all of the Supports: sections and associated brands and models - """ - supports = [] - insupports = False - for line in path.open(encoding="utf-8"): - if not line.startswith("//"): - continue - line = line[2:].strip() - if line == "Supports:": - insupports = True - continue - if insupports: - match = BRAND_MODEL.match(line) - if match: - supports.append((match.group("brand"), match.group("model"))) - else: - insupports = False - continue - # search and inform about any legacy formated supports data - elif any(x in line for x in [ \ - "seems compatible with", - "be compatible with", - "it working with here"]): - print(f"\t{path.name} Legacy supports format found\n\t\t{line}") - return supports - - -def makeurl(txt, path): - """Make a Markup URL from given filename""" - return f"[{txt}]({CODE_URL + path})" - - -def outputprotocols(fout, protocols): - """For a given protocol set, sort and output the markdown""" - protocols = list(protocols) - protocols.sort() - for protocol in protocols: - fout.write(f"- {protocol}\n") - - -def generate(fout): - """Generate data to fout - return True on any issues (when alert is active)""" - decodedprotocols = getdecodedprotocols() - sendonly = getallprotocols() - decodedprotocols - allacs = getallacs() - - sets = getalldevices() - allcodes = sets.allcodes - allbrands = list(allcodes.keys()) - allbrands.sort() - - fout.write("\n# IR Protocols supported by this library\n\n") - fout.write( - "| Protocol | Brand | Model | A/C Model | Detailed A/C Support |\n") - fout.write("| --- | --- | --- | --- | --- |\n") - - for protocolbrand in allbrands: - protocol, brand = protocolbrand - codes = allcodes[protocolbrand] - codes.sort() - acmodels = [] - acsupport = "-" - if protocol in allacs: - acmodels = list(allacs[protocol]) - acmodels.sort() - brand = makeurl(brand, protocol + ".h") - if protocol not in EXCLUDED_ACS: - acsupport = "Yes" - # pylint: disable=C0209 - fout.write("| {} | **{}** | {} | {} | {} |\n".format( - makeurl(protocol, protocol + ".cpp"), - brand, - "
".join(codes).replace("|", "\\|"), - "
".join(acmodels), - acsupport, - )) - # pylint: enable=C0209 - - fout.write("\n\n## Send only protocols:\n\n") - outputprotocols(fout, sendonly) - - fout.write("\n\n## Send & decodable protocols:\n\n") - outputprotocols(fout, decodedprotocols) - - return ARGS.alert and sets.printwarnings() - -def generatenone(): - """No out write - return True on any issues""" - return generate(StringIO()) - -def generatestdout(): - """Standard out write - return True on any issues""" - fout = sys.stdout - fout.write(getmarkdownheader()) - return generate(fout) - -def generatefile(): - """File write, extra detection of changes in existing file - return True on any issues, but only if there is changes""" - # get file path - foutpath = getmdfile() - if ARGS.verbose: - print(f"Output path: {foutpath!s}") - # write data to temp memorystream - ftemp = StringIO() - ret = generate(ftemp) - # get old filedata, skipping header - with getmdfile().open("r", encoding="utf-8") as forg: - olddata = forg.readlines()[3:] - # get new data, skip first empty line - ftemp.seek(0) - newdata = ftemp.readlines()[1:] - # if new data is same as old we don't need to write anything - if newdata == olddata: - print("No changes, exit without write") - return False - # write output - with foutpath.open("w", encoding="utf-8") as fout: - fout.write(getmarkdownheader()) - fout.write(ftemp.getvalue()) - - return ret - -def main(): - """Default main function - return True on any issues""" - initargs() - if ARGS.verbose: - print(f"Looking for files in: {ARGS.directory.resolve()!s}") - if ARGS.noout: - return generatenone() - if ARGS.stdout: - return generatestdout() - # default file - return generatefile() - - -if __name__ == "__main__": - sys.exit(1 if main() else 0) From 26dddb5b7474ed1584e576588dfd85b61decf030 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sat, 20 Nov 2021 12:40:35 +0100 Subject: [PATCH 069/185] Berry animate also returns value (#13744) * Berry animate also returns value * Berry Animate make closure optional --- lib/libesp32/Berry/default/be_animate_lib.c | 539 +++++++++--------- .../Berry/default/embedded/Animate.be | 27 +- 2 files changed, 275 insertions(+), 291 deletions(-) diff --git a/lib/libesp32/Berry/default/be_animate_lib.c b/lib/libesp32/Berry/default/be_animate_lib.c index 3253d25e5..db6052653 100644 --- a/lib/libesp32/Berry/default/be_animate_lib.c +++ b/lib/libesp32/Berry/default/be_animate_lib.c @@ -31,35 +31,32 @@ be_local_closure(Animate_rotate_init, /* name */ }), (be_nested_const_str("init", 380752755, 4)), ((bstring*) &be_const_str_input), - ( &(const binstruction[28]) { /* code */ + ( &(const binstruction[25]) { /* code */ 0x60140003, // 0000 GETGBL R5 G3 0x5C180000, // 0001 MOVE R6 R0 0x7C140200, // 0002 CALL R5 1 0x8C140B00, // 0003 GETMET R5 R5 K0 0x7C140200, // 0004 CALL R5 1 - 0x4C140000, // 0005 LDNIL R5 - 0x20140205, // 0006 NE R5 R1 R5 - 0x78160000, // 0007 JMPF R5 #0009 - 0x90020201, // 0008 SETMBR R0 K1 R1 - 0x88140102, // 0009 GETMBR R5 R0 K2 - 0x8C140B03, // 000A GETMET R5 R5 K3 - 0xB81E0800, // 000B GETNGBL R7 K4 - 0x8C1C0F05, // 000C GETMET R7 R7 K5 - 0x5C240400, // 000D MOVE R9 R2 - 0x5C280600, // 000E MOVE R10 R3 - 0x5C2C0800, // 000F MOVE R11 R4 - 0x7C1C0800, // 0010 CALL R7 4 - 0x7C140400, // 0011 CALL R5 2 - 0x88140102, // 0012 GETMBR R5 R0 K2 - 0x8C140B03, // 0013 GETMET R5 R5 K3 - 0xB81E0800, // 0014 GETNGBL R7 K4 - 0x8C1C0F06, // 0015 GETMET R7 R7 K6 - 0x58240007, // 0016 LDCONST R9 K7 - 0x58280007, // 0017 LDCONST R10 K7 - 0x582C0007, // 0018 LDCONST R11 K7 - 0x7C1C0800, // 0019 CALL R7 4 - 0x7C140400, // 001A CALL R5 2 - 0x80000000, // 001B RET 0 + 0x90020201, // 0005 SETMBR R0 K1 R1 + 0x88140102, // 0006 GETMBR R5 R0 K2 + 0x8C140B03, // 0007 GETMET R5 R5 K3 + 0xB81E0800, // 0008 GETNGBL R7 K4 + 0x8C1C0F05, // 0009 GETMET R7 R7 K5 + 0x5C240400, // 000A MOVE R9 R2 + 0x5C280600, // 000B MOVE R10 R3 + 0x5C2C0800, // 000C MOVE R11 R4 + 0x7C1C0800, // 000D CALL R7 4 + 0x7C140400, // 000E CALL R5 2 + 0x88140102, // 000F GETMBR R5 R0 K2 + 0x8C140B03, // 0010 GETMET R5 R5 K3 + 0xB81E0800, // 0011 GETNGBL R7 K4 + 0x8C1C0F06, // 0012 GETMET R7 R7 K6 + 0x58240007, // 0013 LDCONST R9 K7 + 0x58280007, // 0014 LDCONST R10 K7 + 0x582C0007, // 0015 LDCONST R11 K7 + 0x7C1C0800, // 0016 CALL R7 4 + 0x7C140400, // 0017 CALL R5 2 + 0x80000000, // 0018 RET 0 }) ) ); @@ -103,26 +100,23 @@ be_local_closure(Animate_from_to_init, /* name */ }), (be_nested_const_str("init", 380752755, 4)), ((bstring*) &be_const_str_input), - ( &(const binstruction[19]) { /* code */ + ( &(const binstruction[16]) { /* code */ 0x60140003, // 0000 GETGBL R5 G3 0x5C180000, // 0001 MOVE R6 R0 0x7C140200, // 0002 CALL R5 1 0x8C140B00, // 0003 GETMET R5 R5 K0 0x7C140200, // 0004 CALL R5 1 - 0x4C140000, // 0005 LDNIL R5 - 0x20140205, // 0006 NE R5 R1 R5 - 0x78160000, // 0007 JMPF R5 #0009 - 0x90020201, // 0008 SETMBR R0 K1 R1 - 0x88140102, // 0009 GETMBR R5 R0 K2 - 0x8C140B03, // 000A GETMET R5 R5 K3 - 0xB81E0800, // 000B GETNGBL R7 K4 - 0x8C1C0F05, // 000C GETMET R7 R7 K5 - 0x5C240400, // 000D MOVE R9 R2 - 0x5C280600, // 000E MOVE R10 R3 - 0x5C2C0800, // 000F MOVE R11 R4 - 0x7C1C0800, // 0010 CALL R7 4 - 0x7C140400, // 0011 CALL R5 2 - 0x80000000, // 0012 RET 0 + 0x90020201, // 0005 SETMBR R0 K1 R1 + 0x88140102, // 0006 GETMBR R5 R0 K2 + 0x8C140B03, // 0007 GETMET R5 R5 K3 + 0xB81E0800, // 0008 GETNGBL R7 K4 + 0x8C1C0F05, // 0009 GETMET R7 R7 K5 + 0x5C240400, // 000A MOVE R9 R2 + 0x5C280600, // 000B MOVE R10 R3 + 0x5C2C0800, // 000C MOVE R11 R4 + 0x7C1C0800, // 000D CALL R7 4 + 0x7C140400, // 000E CALL R5 2 + 0x80000000, // 000F RET 0 }) ) ); @@ -169,44 +163,41 @@ be_local_closure(Animate_back_forth_init, /* name */ }), (be_nested_const_str("init", 380752755, 4)), ((bstring*) &be_const_str_input), - ( &(const binstruction[37]) { /* code */ + ( &(const binstruction[34]) { /* code */ 0x60140003, // 0000 GETGBL R5 G3 0x5C180000, // 0001 MOVE R6 R0 0x7C140200, // 0002 CALL R5 1 0x8C140B00, // 0003 GETMET R5 R5 K0 0x7C140200, // 0004 CALL R5 1 - 0x4C140000, // 0005 LDNIL R5 - 0x20140205, // 0006 NE R5 R1 R5 - 0x78160000, // 0007 JMPF R5 #0009 - 0x90020201, // 0008 SETMBR R0 K1 R1 - 0x88140102, // 0009 GETMBR R5 R0 K2 - 0x8C140B03, // 000A GETMET R5 R5 K3 - 0xB81E0800, // 000B GETNGBL R7 K4 - 0x8C1C0F05, // 000C GETMET R7 R7 K5 - 0x5C240400, // 000D MOVE R9 R2 - 0x5C280600, // 000E MOVE R10 R3 - 0x0C2C0906, // 000F DIV R11 R4 K6 - 0x7C1C0800, // 0010 CALL R7 4 - 0x7C140400, // 0011 CALL R5 2 - 0x88140102, // 0012 GETMBR R5 R0 K2 - 0x8C140B03, // 0013 GETMET R5 R5 K3 - 0xB81E0800, // 0014 GETNGBL R7 K4 - 0x8C1C0F05, // 0015 GETMET R7 R7 K5 - 0x5C240600, // 0016 MOVE R9 R3 - 0x5C280400, // 0017 MOVE R10 R2 - 0x0C2C0906, // 0018 DIV R11 R4 K6 - 0x7C1C0800, // 0019 CALL R7 4 - 0x7C140400, // 001A CALL R5 2 - 0x88140102, // 001B GETMBR R5 R0 K2 - 0x8C140B03, // 001C GETMET R5 R5 K3 - 0xB81E0800, // 001D GETNGBL R7 K4 - 0x8C1C0F07, // 001E GETMET R7 R7 K7 - 0x58240008, // 001F LDCONST R9 K8 - 0x58280008, // 0020 LDCONST R10 K8 - 0x582C0008, // 0021 LDCONST R11 K8 - 0x7C1C0800, // 0022 CALL R7 4 - 0x7C140400, // 0023 CALL R5 2 - 0x80000000, // 0024 RET 0 + 0x90020201, // 0005 SETMBR R0 K1 R1 + 0x88140102, // 0006 GETMBR R5 R0 K2 + 0x8C140B03, // 0007 GETMET R5 R5 K3 + 0xB81E0800, // 0008 GETNGBL R7 K4 + 0x8C1C0F05, // 0009 GETMET R7 R7 K5 + 0x5C240400, // 000A MOVE R9 R2 + 0x5C280600, // 000B MOVE R10 R3 + 0x0C2C0906, // 000C DIV R11 R4 K6 + 0x7C1C0800, // 000D CALL R7 4 + 0x7C140400, // 000E CALL R5 2 + 0x88140102, // 000F GETMBR R5 R0 K2 + 0x8C140B03, // 0010 GETMET R5 R5 K3 + 0xB81E0800, // 0011 GETNGBL R7 K4 + 0x8C1C0F05, // 0012 GETMET R7 R7 K5 + 0x5C240600, // 0013 MOVE R9 R3 + 0x5C280400, // 0014 MOVE R10 R2 + 0x0C2C0906, // 0015 DIV R11 R4 K6 + 0x7C1C0800, // 0016 CALL R7 4 + 0x7C140400, // 0017 CALL R5 2 + 0x88140102, // 0018 GETMBR R5 R0 K2 + 0x8C140B03, // 0019 GETMET R5 R5 K3 + 0xB81E0800, // 001A GETNGBL R7 K4 + 0x8C1C0F07, // 001B GETMET R7 R7 K7 + 0x58240008, // 001C LDCONST R9 K8 + 0x58280008, // 001D LDCONST R10 K8 + 0x582C0008, // 001E LDCONST R11 K8 + 0x7C1C0800, // 001F CALL R7 4 + 0x7C140400, // 0020 CALL R5 2 + 0x80000000, // 0021 RET 0 }) ) ); @@ -321,71 +312,49 @@ be_local_class(Animate_ins_ramp, (be_nested_const_str("Animate_ins_ramp", 785058280, 16)) ); -/******************************************************************** -** Solidified function: is_running -********************************************************************/ -be_local_closure(Animate_engine_is_running, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_string("running", 343848780, 7), - }), - (be_nested_const_str("is_running", -2068120035, 10)), - ((bstring*) &be_const_str_input), - ( &(const binstruction[ 2]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x80040200, // 0001 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified function: run ********************************************************************/ be_local_closure(Animate_engine_run, /* name */ be_nested_proto( - 5, /* nstack */ - 2, /* argc */ + 6, /* nstack */ + 3, /* argc */ 0, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ + ( &(const bvalue[ 6]) { /* constants */ /* K0 */ be_nested_string("tasmota", 424643812, 7), /* K1 */ be_nested_string("millis", 1214679063, 6), - /* K2 */ be_nested_string("ins_time", -1314721743, 8), - /* K3 */ be_nested_string("running", 343848780, 7), - /* K4 */ be_nested_string("add_driver", 1654458371, 10), + /* K2 */ be_nested_string("value", 1113510858, 5), + /* K3 */ be_nested_string("ins_time", -1314721743, 8), + /* K4 */ be_nested_string("running", 343848780, 7), + /* K5 */ be_nested_string("add_driver", 1654458371, 10), }), (be_nested_const_str("run", 718098122, 3)), ((bstring*) &be_const_str_input), - ( &(const binstruction[15]) { /* code */ - 0x4C080000, // 0000 LDNIL R2 - 0x1C080202, // 0001 EQ R2 R1 R2 - 0x780A0003, // 0002 JMPF R2 #0007 - 0xB80A0000, // 0003 GETNGBL R2 K0 - 0x8C080501, // 0004 GETMET R2 R2 K1 - 0x7C080200, // 0005 CALL R2 1 - 0x5C040400, // 0006 MOVE R1 R2 - 0x90020401, // 0007 SETMBR R0 K2 R1 - 0x50080200, // 0008 LDBOOL R2 1 0 - 0x90020602, // 0009 SETMBR R0 K3 R2 - 0xB80A0000, // 000A GETNGBL R2 K0 - 0x8C080504, // 000B GETMET R2 R2 K4 - 0x5C100000, // 000C MOVE R4 R0 - 0x7C080400, // 000D CALL R2 2 - 0x80000000, // 000E RET 0 + ( &(const binstruction[19]) { /* code */ + 0x4C0C0000, // 0000 LDNIL R3 + 0x1C0C0203, // 0001 EQ R3 R1 R3 + 0x780E0003, // 0002 JMPF R3 #0007 + 0xB80E0000, // 0003 GETNGBL R3 K0 + 0x8C0C0701, // 0004 GETMET R3 R3 K1 + 0x7C0C0200, // 0005 CALL R3 1 + 0x5C040600, // 0006 MOVE R1 R3 + 0x4C0C0000, // 0007 LDNIL R3 + 0x200C0403, // 0008 NE R3 R2 R3 + 0x780E0000, // 0009 JMPF R3 #000B + 0x90020402, // 000A SETMBR R0 K2 R2 + 0x90020601, // 000B SETMBR R0 K3 R1 + 0x500C0200, // 000C LDBOOL R3 1 0 + 0x90020803, // 000D SETMBR R0 K4 R3 + 0xB80E0000, // 000E GETNGBL R3 K0 + 0x8C0C0705, // 000F GETMET R3 R3 K5 + 0x5C140000, // 0010 MOVE R5 R0 + 0x7C0C0400, // 0011 CALL R3 2 + 0x80000000, // 0012 RET 0 }) ) ); @@ -402,53 +371,27 @@ be_local_closure(Animate_engine_init, /* name */ 0, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ - 1, /* has sup protos */ - ( &(const struct bproto*[ 1]) { - be_nested_proto( - 4, /* nstack */ - 1, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_string("Animate next value:", 443143038, 19), - }), - (be_nested_const_str("_anonymous_", 1957281476, 11)), - ((bstring*) &be_const_str_input), - ( &(const binstruction[ 5]) { /* code */ - 0x60040001, // 0000 GETGBL R1 G1 - 0x58080000, // 0001 LDCONST R2 K0 - 0x5C0C0000, // 0002 MOVE R3 R0 - 0x7C040400, // 0003 CALL R1 2 - 0x80000000, // 0004 RET 0 - }) - ), - }), + 0, /* has sup protos */ + NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ + ( &(const bvalue[ 5]) { /* constants */ /* K0 */ be_nested_string("code", -114201356, 4), - /* K1 */ be_nested_string("closure", 1548407746, 7), - /* K2 */ be_nested_string("pc", 1313756516, 2), - /* K3 */ be_const_int(0), - /* K4 */ be_nested_string("ins_time", -1314721743, 8), - /* K5 */ be_nested_string("running", 343848780, 7), + /* K1 */ be_nested_string("pc", 1313756516, 2), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_string("ins_time", -1314721743, 8), + /* K4 */ be_nested_string("running", 343848780, 7), }), (be_nested_const_str("init", 380752755, 4)), ((bstring*) &be_const_str_input), - ( &(const binstruction[10]) { /* code */ + ( &(const binstruction[ 8]) { /* code */ 0x60040012, // 0000 GETGBL R1 G18 0x7C040000, // 0001 CALL R1 0 0x90020001, // 0002 SETMBR R0 K0 R1 - 0x84040000, // 0003 CLOSURE R1 P0 - 0x90020201, // 0004 SETMBR R0 K1 R1 - 0x90020503, // 0005 SETMBR R0 K2 K3 - 0x90020903, // 0006 SETMBR R0 K4 K3 - 0x50040000, // 0007 LDBOOL R1 0 0 - 0x90020A01, // 0008 SETMBR R0 K5 R1 - 0x80000000, // 0009 RET 0 + 0x90020302, // 0003 SETMBR R0 K1 K2 + 0x90020702, // 0004 SETMBR R0 K3 K2 + 0x50040000, // 0005 LDBOOL R1 0 0 + 0x90020801, // 0006 SETMBR R0 K4 R1 + 0x80000000, // 0007 RET 0 }) ) ); @@ -456,27 +399,35 @@ be_local_closure(Animate_engine_init, /* name */ /******************************************************************** -** Solidified function: every_50ms +** Solidified function: autorun ********************************************************************/ -be_local_closure(Animate_engine_every_50ms, /* name */ +be_local_closure(Animate_engine_autorun, /* name */ be_nested_proto( - 3, /* nstack */ - 1, /* argc */ + 7, /* nstack */ + 3, /* argc */ 0, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_string("animate", -409180496, 7), + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_string("run", 718098122, 3), + /* K1 */ be_nested_string("tasmota", 424643812, 7), + /* K2 */ be_nested_string("add_driver", 1654458371, 10), }), - (be_nested_const_str("every_50ms", -1911083288, 10)), + (be_nested_const_str("autorun", 1447527407, 7)), ((bstring*) &be_const_str_input), - ( &(const binstruction[ 3]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x7C040200, // 0001 CALL R1 1 - 0x80000000, // 0002 RET 0 + ( &(const binstruction[ 9]) { /* code */ + 0x8C0C0100, // 0000 GETMET R3 R0 K0 + 0x5C140200, // 0001 MOVE R5 R1 + 0x5C180400, // 0002 MOVE R6 R2 + 0x7C0C0600, // 0003 CALL R3 3 + 0xB80E0200, // 0004 GETNGBL R3 K1 + 0x8C0C0702, // 0005 GETMET R3 R3 K2 + 0x5C140000, // 0006 MOVE R5 R0 + 0x7C0C0400, // 0007 CALL R3 2 + 0x80000000, // 0008 RET 0 }) ) ); @@ -517,6 +468,61 @@ be_local_closure(Animate_engine_stop, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: is_running +********************************************************************/ +be_local_closure(Animate_engine_is_running, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_string("running", 343848780, 7), + }), + (be_nested_const_str("is_running", -2068120035, 10)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: every_50ms +********************************************************************/ +be_local_closure(Animate_engine_every_50ms, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_string("animate", -409180496, 7), + }), + (be_nested_const_str("every_50ms", -1911083288, 10)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 3]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x7C040200, // 0001 CALL R1 1 + 0x80000000, // 0002 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: animate ********************************************************************/ @@ -530,7 +536,7 @@ be_local_closure(Animate_engine_animate, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[21]) { /* constants */ + ( &(const bvalue[22]) { /* constants */ /* K0 */ be_nested_string("running", 343848780, 7), /* K1 */ be_nested_string("tasmota", 424643812, 7), /* K2 */ be_nested_string("millis", 1214679063, 6), @@ -544,18 +550,19 @@ be_local_closure(Animate_engine_animate, /* name */ /* K10 */ be_nested_string("ins_ramp", 1068049360, 8), /* K11 */ be_nested_string("closure", 1548407746, 7), /* K12 */ be_nested_string("duration", 799079693, 8), - /* K13 */ be_nested_string("scale_uint", -1204156202, 10), - /* K14 */ be_nested_string("a", -468965076, 1), - /* K15 */ be_nested_string("b", -418632219, 1), - /* K16 */ be_const_int(1), - /* K17 */ be_nested_string("ins_goto", 1342843963, 8), - /* K18 */ be_nested_string("pc_rel", 991921176, 6), - /* K19 */ be_nested_string("pc_abs", 920256495, 6), - /* K20 */ be_nested_string("unknown instruction", 1093911841, 19), + /* K13 */ be_nested_string("value", 1113510858, 5), + /* K14 */ be_nested_string("scale_uint", -1204156202, 10), + /* K15 */ be_nested_string("a", -468965076, 1), + /* K16 */ be_nested_string("b", -418632219, 1), + /* K17 */ be_const_int(1), + /* K18 */ be_nested_string("ins_goto", 1342843963, 8), + /* K19 */ be_nested_string("pc_rel", 991921176, 6), + /* K20 */ be_nested_string("pc_abs", 920256495, 6), + /* K21 */ be_nested_string("unknown instruction", 1093911841, 19), }), (be_nested_const_str("animate", -409180496, 7)), ((bstring*) &be_const_str_input), - ( &(const binstruction[93]) { /* code */ + ( &(const binstruction[99]) { /* code */ 0x88080100, // 0000 GETMBR R2 R0 K0 0x740A0000, // 0001 JMPT R2 #0003 0x80000400, // 0002 RET 0 @@ -567,7 +574,7 @@ be_local_closure(Animate_engine_animate, /* name */ 0x7C080200, // 0008 CALL R2 1 0x5C040400, // 0009 MOVE R1 R2 0x50080200, // 000A LDBOOL R2 1 0 - 0x780A004F, // 000B JMPF R2 #005C + 0x780A0054, // 000B JMPF R2 #0061 0x88080103, // 000C GETMBR R2 R0 K3 0x04080202, // 000D SUB R2 R1 R2 0x880C0104, // 000E GETMBR R3 R0 K4 @@ -578,7 +585,7 @@ be_local_closure(Animate_engine_animate, /* name */ 0x780E0002, // 0013 JMPF R3 #0017 0x500C0000, // 0014 LDBOOL R3 0 0 0x90020003, // 0015 SETMBR R0 K0 R3 - 0x70020044, // 0016 JMP #005C + 0x70020049, // 0016 JMP #0061 0x880C0104, // 0017 GETMBR R3 R0 K4 0x140C0706, // 0018 LT R3 R3 K6 0x780E0000, // 0019 JMPF R3 #001B @@ -591,99 +598,70 @@ be_local_closure(Animate_engine_animate, /* name */ 0xB81E1200, // 0020 GETNGBL R7 K9 0x881C0F0A, // 0021 GETMBR R7 R7 K10 0x7C140400, // 0022 CALL R5 2 - 0x7816001B, // 0023 JMPF R5 #0040 + 0x78160020, // 0023 JMPF R5 #0045 0x8810010B, // 0024 GETMBR R4 R0 K11 0x8814070C, // 0025 GETMBR R5 R3 K12 0x14140405, // 0026 LT R5 R2 R5 - 0x7816000C, // 0027 JMPF R5 #0035 + 0x7816000E, // 0027 JMPF R5 #0037 0xB8160200, // 0028 GETNGBL R5 K1 - 0x8C140B0D, // 0029 GETMET R5 R5 K13 + 0x8C140B0E, // 0029 GETMET R5 R5 K14 0x5C1C0400, // 002A MOVE R7 R2 0x58200006, // 002B LDCONST R8 K6 0x8824070C, // 002C GETMBR R9 R3 K12 - 0x8828070E, // 002D GETMBR R10 R3 K14 - 0x882C070F, // 002E GETMBR R11 R3 K15 + 0x8828070F, // 002D GETMBR R10 R3 K15 + 0x882C0710, // 002E GETMBR R11 R3 K16 0x7C140C00, // 002F CALL R5 6 - 0x5C180800, // 0030 MOVE R6 R4 - 0x5C1C0A00, // 0031 MOVE R7 R5 - 0x7C180200, // 0032 CALL R6 1 - 0x70020027, // 0033 JMP #005C - 0x70020009, // 0034 JMP #003F - 0x5C140800, // 0035 MOVE R5 R4 - 0x8818070F, // 0036 GETMBR R6 R3 K15 - 0x7C140200, // 0037 CALL R5 1 - 0x88140104, // 0038 GETMBR R5 R0 K4 - 0x00140B10, // 0039 ADD R5 R5 K16 - 0x90020805, // 003A SETMBR R0 K4 R5 - 0x8814070C, // 003B GETMBR R5 R3 K12 - 0x04140405, // 003C SUB R5 R2 R5 - 0x04140205, // 003D SUB R5 R1 R5 - 0x90020605, // 003E SETMBR R0 K3 R5 - 0x7002001A, // 003F JMP #005B - 0x6010000F, // 0040 GETGBL R4 G15 - 0x5C140600, // 0041 MOVE R5 R3 - 0xB81A1200, // 0042 GETNGBL R6 K9 - 0x88180D11, // 0043 GETMBR R6 R6 K17 - 0x7C100400, // 0044 CALL R4 2 - 0x78120013, // 0045 JMPF R4 #005A - 0x8810070C, // 0046 GETMBR R4 R3 K12 - 0x14100404, // 0047 LT R4 R2 R4 - 0x78120001, // 0048 JMPF R4 #004B - 0x70020011, // 0049 JMP #005C - 0x7002000D, // 004A JMP #0059 - 0x88100712, // 004B GETMBR R4 R3 K18 - 0x20100906, // 004C NE R4 R4 K6 - 0x78120004, // 004D JMPF R4 #0053 - 0x88100104, // 004E GETMBR R4 R0 K4 - 0x88140712, // 004F GETMBR R5 R3 K18 - 0x00100805, // 0050 ADD R4 R4 R5 - 0x90020804, // 0051 SETMBR R0 K4 R4 - 0x70020001, // 0052 JMP #0055 - 0x88100713, // 0053 GETMBR R4 R3 K19 - 0x90020804, // 0054 SETMBR R0 K4 R4 - 0x8810070C, // 0055 GETMBR R4 R3 K12 - 0x04100404, // 0056 SUB R4 R2 R4 - 0x04100204, // 0057 SUB R4 R1 R4 - 0x90020604, // 0058 SETMBR R0 K3 R4 - 0x70020000, // 0059 JMP #005B - 0xB0060F14, // 005A RAISE 1 K7 K20 - 0x7001FFAD, // 005B JMP #000A - 0x80000000, // 005C RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: autorun -********************************************************************/ -be_local_closure(Animate_engine_autorun, /* name */ - be_nested_proto( - 5, /* nstack */ - 2, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_string("run", 718098122, 3), - /* K1 */ be_nested_string("tasmota", 424643812, 7), - /* K2 */ be_nested_string("add_driver", 1654458371, 10), - }), - (be_nested_const_str("autorun", 1447527407, 7)), - ((bstring*) &be_const_str_input), - ( &(const binstruction[ 8]) { /* code */ - 0x8C080100, // 0000 GETMET R2 R0 K0 - 0x5C100200, // 0001 MOVE R4 R1 - 0x7C080400, // 0002 CALL R2 2 - 0xB80A0200, // 0003 GETNGBL R2 K1 - 0x8C080502, // 0004 GETMET R2 R2 K2 - 0x5C100000, // 0005 MOVE R4 R0 - 0x7C080400, // 0006 CALL R2 2 - 0x80000000, // 0007 RET 0 + 0x90021A05, // 0030 SETMBR R0 K13 R5 + 0x78120002, // 0031 JMPF R4 #0035 + 0x5C140800, // 0032 MOVE R5 R4 + 0x8818010D, // 0033 GETMBR R6 R0 K13 + 0x7C140200, // 0034 CALL R5 1 + 0x7002002A, // 0035 JMP #0061 + 0x7002000C, // 0036 JMP #0044 + 0x88140710, // 0037 GETMBR R5 R3 K16 + 0x90021A05, // 0038 SETMBR R0 K13 R5 + 0x78120002, // 0039 JMPF R4 #003D + 0x5C140800, // 003A MOVE R5 R4 + 0x8818010D, // 003B GETMBR R6 R0 K13 + 0x7C140200, // 003C CALL R5 1 + 0x88140104, // 003D GETMBR R5 R0 K4 + 0x00140B11, // 003E ADD R5 R5 K17 + 0x90020805, // 003F SETMBR R0 K4 R5 + 0x8814070C, // 0040 GETMBR R5 R3 K12 + 0x04140405, // 0041 SUB R5 R2 R5 + 0x04140205, // 0042 SUB R5 R1 R5 + 0x90020605, // 0043 SETMBR R0 K3 R5 + 0x7002001A, // 0044 JMP #0060 + 0x6010000F, // 0045 GETGBL R4 G15 + 0x5C140600, // 0046 MOVE R5 R3 + 0xB81A1200, // 0047 GETNGBL R6 K9 + 0x88180D12, // 0048 GETMBR R6 R6 K18 + 0x7C100400, // 0049 CALL R4 2 + 0x78120013, // 004A JMPF R4 #005F + 0x8810070C, // 004B GETMBR R4 R3 K12 + 0x14100404, // 004C LT R4 R2 R4 + 0x78120001, // 004D JMPF R4 #0050 + 0x70020011, // 004E JMP #0061 + 0x7002000D, // 004F JMP #005E + 0x88100713, // 0050 GETMBR R4 R3 K19 + 0x20100906, // 0051 NE R4 R4 K6 + 0x78120004, // 0052 JMPF R4 #0058 + 0x88100104, // 0053 GETMBR R4 R0 K4 + 0x88140713, // 0054 GETMBR R5 R3 K19 + 0x00100805, // 0055 ADD R4 R4 R5 + 0x90020804, // 0056 SETMBR R0 K4 R4 + 0x70020001, // 0057 JMP #005A + 0x88100714, // 0058 GETMBR R4 R3 K20 + 0x90020804, // 0059 SETMBR R0 K4 R4 + 0x8810070C, // 005A GETMBR R4 R3 K12 + 0x04100404, // 005B SUB R4 R2 R4 + 0x04100204, // 005C SUB R4 R1 R4 + 0x90020604, // 005D SETMBR R0 K3 R4 + 0x70020000, // 005E JMP #0060 + 0xB0060F15, // 005F RAISE 1 K7 K21 + 0x7001FFA8, // 0060 JMP #000A + 0x8808010D, // 0061 GETMBR R2 R0 K13 + 0x80040400, // 0062 RET 1 R2 }) ) ); @@ -694,22 +672,23 @@ be_local_closure(Animate_engine_autorun, /* name */ ** Solidified class: Animate_engine ********************************************************************/ be_local_class(Animate_engine, - 5, + 6, NULL, - be_nested_map(12, + be_nested_map(13, ( (struct bmapnode*) &(const bmapnode[]) { - { be_nested_key("running", 343848780, 7, -1), be_const_var(4) }, - { be_nested_key("is_running", -2068120035, 10, 7), be_const_closure(Animate_engine_is_running_closure) }, - { be_nested_key("run", 718098122, 3, -1), be_const_closure(Animate_engine_run_closure) }, + { be_nested_key("code", -114201356, 4, -1), be_const_var(0) }, + { be_nested_key("run", 718098122, 3, 4), be_const_closure(Animate_engine_run_closure) }, + { be_nested_key("running", 343848780, 7, 8), be_const_var(4) }, { be_nested_key("init", 380752755, 4, -1), be_const_closure(Animate_engine_init_closure) }, - { be_nested_key("every_50ms", -1911083288, 10, -1), be_const_closure(Animate_engine_every_50ms_closure) }, - { be_nested_key("stop", -883741979, 4, -1), be_const_closure(Animate_engine_stop_closure) }, - { be_nested_key("pc", 1313756516, 2, 4), be_const_var(2) }, - { be_nested_key("ins_time", -1314721743, 8, -1), be_const_var(3) }, - { be_nested_key("animate", -409180496, 7, 9), be_const_closure(Animate_engine_animate_closure) }, - { be_nested_key("code", -114201356, 4, 6), be_const_var(0) }, - { be_nested_key("closure", 1548407746, 7, -1), be_const_var(1) }, { be_nested_key("autorun", 1447527407, 7, -1), be_const_closure(Animate_engine_autorun_closure) }, + { be_nested_key("value", 1113510858, 5, -1), be_const_var(5) }, + { be_nested_key("stop", -883741979, 4, 3), be_const_closure(Animate_engine_stop_closure) }, + { be_nested_key("pc", 1313756516, 2, -1), be_const_var(2) }, + { be_nested_key("is_running", -2068120035, 10, 11), be_const_closure(Animate_engine_is_running_closure) }, + { be_nested_key("every_50ms", -1911083288, 10, 10), be_const_closure(Animate_engine_every_50ms_closure) }, + { be_nested_key("animate", -409180496, 7, -1), be_const_closure(Animate_engine_animate_closure) }, + { be_nested_key("closure", 1548407746, 7, -1), be_const_var(1) }, + { be_nested_key("ins_time", -1314721743, 8, 9), be_const_var(3) }, })), (be_nested_const_str("Animate_engine", 1498417667, 14)) ); diff --git a/lib/libesp32/Berry/default/embedded/Animate.be b/lib/libesp32/Berry/default/embedded/Animate.be index 6f4f28fcc..279fd39ed 100644 --- a/lib/libesp32/Berry/default/embedded/Animate.be +++ b/lib/libesp32/Berry/default/embedded/Animate.be @@ -40,10 +40,10 @@ class Animate_engine var pc # program-counter var ins_time # absolute time when the current instruction started var running # is the animation running? allows fast return + var value # current value def init() self.code = [] - self.closure = def (v) print("Animate next value:", v) end # default to debug function self.pc = 0 # start at instruction 0 self.ins_time = 0 self.running = false # not running by default @@ -51,8 +51,11 @@ class Animate_engine end # run but needs external calls to `animate()` - def run(cur_time) + # cur_time:int (opt) current timestamp in ms, defaults to `tasmota.millis()` + # val:int (opt) starting value, default to `nil` + def run(cur_time, val) if cur_time == nil cur_time = tasmota.millis() end + if (val != nil) self.value = val end self.ins_time = cur_time self.running = true @@ -60,8 +63,8 @@ class Animate_engine end # runs autonomously in the Tasmota event loop - def autorun(cur_time) - self.run(cur_time) + def autorun(cur_time, val) + self.run(cur_time, val) tasmota.add_driver(self) end @@ -96,15 +99,16 @@ class Animate_engine # Instruction Ramp if isinstance(ins, animate.ins_ramp) - var f = self.closure # assign to a local variable to not call a method + var f = self.closure # assign to a local variable to not call a method if sub_index < ins.duration # we're still in the ramp - var v = tasmota.scale_uint(sub_index, 0, ins.duration, ins.a, ins.b) + self.value = tasmota.scale_uint(sub_index, 0, ins.duration, ins.a, ins.b) # call closure - f(v) # call closure, need try? TODO + if f f(self.value) end # call closure, need try? TODO break else - f(ins.b) # set to last value + self.value = ins.b + if f f(self.value) end # set to last value self.pc += 1 # next instruction self.ins_time = cur_time - (sub_index - ins.duration) end @@ -127,6 +131,7 @@ class Animate_engine raise "internal_error", "unknown instruction" end end + return self.value end end @@ -136,7 +141,7 @@ class Animate_from_to : Animate_engine def init(closure, from, to, duration) super(self).init() - if closure != nil self.closure = closure end + self.closure = closure self.code.push(animate.ins_ramp(from, to, duration)) end @@ -152,7 +157,7 @@ class Animate_rotate : Animate_engine def init(closure, from, to, duration) super(self).init() - if closure != nil self.closure = closure end + self.closure = closure self.code.push(animate.ins_ramp(from, to, duration)) self.code.push(animate.ins_goto(0, 0, 0)) # goto abs pc = 0 without any pause end @@ -169,7 +174,7 @@ class Animate_back_forth : Animate_engine def init(closure, from, to, duration) super(self).init() - if closure != nil self.closure = closure end + self.closure = closure self.code.push(animate.ins_ramp(from, to, duration / 2)) self.code.push(animate.ins_ramp(to, from, duration / 2)) self.code.push(animate.ins_goto(0, 0, 0)) # goto abs pc = 0 without any pause From cc5f799bdf8783a72930738b976f9d443963d288 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sat, 20 Nov 2021 12:40:46 +0100 Subject: [PATCH 070/185] Plug zip (#13746) --- tasmota/xdrv_54_lvgl.ino | 40 ++++++++++++---------------------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/tasmota/xdrv_54_lvgl.ino b/tasmota/xdrv_54_lvgl.ino index c8f533310..e772ea910 100644 --- a/tasmota/xdrv_54_lvgl.ino +++ b/tasmota/xdrv_54_lvgl.ino @@ -121,6 +121,12 @@ void lv_flush_callback(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *c ************************************************************/ #ifdef USE_UFILESYS + +#include +#include "ZipReadFS.h" +extern FS *ffsp; +FS lv_zip_ufsp(ZipReadFSImplPtr(new ZipReadFSImpl(&ffsp))); + extern "C" { typedef void lvbe_FILE; @@ -132,7 +138,7 @@ extern "C" { String file_path = "/"; file_path += filename; - File f = dfsp->open(file_path, mode); + File f = lv_zip_ufsp.open(file_path, mode); // AddLog(LOG_LEVEL_INFO, "LVG: lvbe_fopen(%s) -> %i", file_path.c_str(), (int32_t)f); // AddLog(LOG_LEVEL_INFO, "LVG: F=%*_H", sizeof(f), &f); if (f) { @@ -202,15 +208,9 @@ static void * lvbe_fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mo // AddLog(LOG_LEVEL_INFO, "LVG: lvbe_fs_open(%p, %p, %s, %i) %i", drv, file_p, path, mode, sizeof(File)); const char * modes = nullptr; switch (mode) { - case LV_FS_MODE_WR: - modes = "w"; - break; - case LV_FS_MODE_RD: - modes = "r"; - break; - case LV_FS_MODE_WR | LV_FS_MODE_RD: - modes = "rw"; - break; + case LV_FS_MODE_WR: modes = "w"; break; + case LV_FS_MODE_RD: modes = "r"; break; + case LV_FS_MODE_WR | LV_FS_MODE_RD: modes = "rw"; break; } if (modes == nullptr) { @@ -218,28 +218,12 @@ static void * lvbe_fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mo return nullptr; } - // Add "/" prefix - String file_path = "/"; - file_path += path; - - File f = dfsp->open(file_path.c_str(), modes); - // AddLog(LOG_LEVEL_INFO, "LVG: lvbe_fs_open(%s) -> %i", file_path.c_str(), (int32_t)f); - // AddLog(LOG_LEVEL_INFO, "LVG: F=%*_H", sizeof(f), &f); - if (f) { - File * f_ptr = new File(f); // copy to dynamic object - return f_ptr; - } else { - return nullptr; - } + return (void*) lvbe_fopen(path, modes); } static lv_fs_res_t lvbe_fs_close(lv_fs_drv_t * drv, void * file_p); static lv_fs_res_t lvbe_fs_close(lv_fs_drv_t * drv, void * file_p) { - // AddLog(LOG_LEVEL_INFO, "LVG: lvbe_fs_close(%p, %p)", drv, file_p); - File * f_ptr = (File*) file_p; - f_ptr->close(); - delete f_ptr; - return LV_FS_RES_OK; + return lvbe_fclose((void*)file_p); } static lv_fs_res_t lvbe_fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br); From 476c2b3dc0d750f171ae7e1b2014291d96f574a8 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 20 Nov 2021 13:00:35 +0100 Subject: [PATCH 071/185] IRremoteESP8266 library from v2.7.20 to v2.8.0 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 448585921..bf22faf1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ All notable changes to this project will be documented in this file. ### Changed - ESP8266 Gratuitous ARP enabled and set to 60 seconds (#13623) - Removed ILI9488 driver in favor of Unversal Display Driver +- IRremoteESP8266 library from v2.7.20 to v2.8.0 (#13738) ## [10.0.0.2] 20211113 ### Added From 6999f875666258be7c96dad0964e45bac620fd05 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 20 Nov 2021 14:13:54 +0100 Subject: [PATCH 072/185] Fix exception 0 when width is 0 --- tasmota/xlgt_01_ws2812.ino | 75 +++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/tasmota/xlgt_01_ws2812.ino b/tasmota/xlgt_01_ws2812.ino index e0030dcb8..bc8dd5f85 100644 --- a/tasmota/xlgt_01_ws2812.ino +++ b/tasmota/xlgt_01_ws2812.ino @@ -24,15 +24,15 @@ * * light_scheme WS2812 3+ Colors 1+2 Colors Effect * ------------ ------ --------- ---------- ----------------- - * 0 yes no no Clock - * 1 yes no no Incandescent - * 2 yes no no RGB - * 3 yes no no Christmas - * 4 yes no no Hanukkah - * 5 yes no no Kwanzaa - * 6 yes no no Rainbow - * 7 yes no no Fire - * + * 0 (5) yes no no Clock + * 1 (6) yes no no Incandescent + * 2 (7) yes no no RGB + * 3 (8) yes no no Christmas + * 4 (9) yes no no Hanukkah + * 5 (10) yes no no Kwanzaa + * 6 (11) yes no no Rainbow + * 7 (12) yes no no Fire + * 8 (13) yes no no Stairs \*********************************************************************************************/ #define XLGT_01 1 @@ -174,7 +174,7 @@ ColorScheme kSchemes[WS2812_SCHEMES -1] = { // Skip clock scheme kHanukkah, 2, kwanzaa, 3, kRainbow, 7, - kFire, 3, + kFire, 3, kStairs, 2 }; uint8_t kWidth[5] = { @@ -401,8 +401,7 @@ void Ws2812Bars(uint32_t schemenr) Ws2812StripShow(); } -void Ws2812Steps(uint32_t schemenr) -{ +void Ws2812Steps(uint32_t schemenr) { #if (USE_WS2812_CTYPE > NEO_3LED) RgbwColor c; c.W = 0; @@ -412,29 +411,32 @@ void Ws2812Steps(uint32_t schemenr) ColorScheme scheme = kSchemes[schemenr]; // apply main color if current sheme == kStairs - if(scheme.colors == kStairs){ + if (scheme.colors == kStairs) { scheme.colors[1].red = Settings->light_color[0]; scheme.colors[1].green = Settings->light_color[1]; scheme.colors[1].blue = Settings->light_color[2]; } - uint8_t scheme_count=scheme.count; - if(Settings->light_fade){ - scheme_count=Settings->ws_width[WS_HOUR];//Width4 + uint8_t scheme_count = scheme.count; + if (Settings->light_fade) { + scheme_count = Settings->ws_width[WS_HOUR]; // Width4 } + if (scheme_count < 2) { + scheme_count = 2; + } WsColor mcolor[scheme_count]; - uint8_t color_start=0; - uint8_t color_end=1; - if(Settings->light_rotation & 0x01){ - color_start=1; - color_end=0; + uint8_t color_start = 0; + uint8_t color_end = 1; + if (Settings->light_rotation & 0x01) { + color_start = 1; + color_end = 0; } - if(Settings->light_fade){ + if (Settings->light_fade) { // generate gradient (width = Width4) - for(uint32_t i=1; i < scheme_count - 1; i++){ + for (uint32_t i = 1; i < scheme_count - 1; i++) { mcolor[i].red = (uint8_t) wsmap(i, 0, scheme_count, scheme.colors[color_start].red, scheme.colors[color_end].red); mcolor[i].green = (uint8_t) wsmap(i, 0, scheme_count, scheme.colors[color_start].green, scheme.colors[color_end].green); mcolor[i].blue = (uint8_t) wsmap(i, 0, scheme_count, scheme.colors[color_start].blue, scheme.colors[color_end].blue); @@ -442,14 +444,13 @@ void Ws2812Steps(uint32_t schemenr) } else { memcpy(mcolor, scheme.colors, sizeof(mcolor)); } - // repair first & last color in gradient; apply scheme rotation if fade==0 - mcolor[0].red=scheme.colors[color_start].red; - mcolor[0].green=scheme.colors[color_start].green; - mcolor[0].blue=scheme.colors[color_start].blue; - mcolor[scheme_count-1].red=scheme.colors[color_end].red; - mcolor[scheme_count-1].green=scheme.colors[color_end].green; - mcolor[scheme_count-1].blue=scheme.colors[color_end].blue; - + // Repair first & last color in gradient; apply scheme rotation if fade==0 + mcolor[0].red = scheme.colors[color_start].red; + mcolor[0].green = scheme.colors[color_start].green; + mcolor[0].blue = scheme.colors[color_start].blue; + mcolor[scheme_count-1].red = scheme.colors[color_end].red; + mcolor[scheme_count-1].green = scheme.colors[color_end].green; + mcolor[scheme_count-1].blue = scheme.colors[color_end].blue; // Adjust to dimmer value float dimmer = 100 / (float)Settings->light_dimmer; @@ -466,23 +467,23 @@ void Ws2812Steps(uint32_t schemenr) int32_t current_position = Light.strip_timer_counter / speed; //all pixels are shown already | rotation change will not change current state - if(current_position > Settings->light_pixels / Settings->light_step_pixels + scheme_count ) { + if (current_position > Settings->light_pixels / Settings->light_step_pixels + scheme_count ) { return; } int32_t colorIndex; int32_t step_nr; - + for (uint32_t i = 0; i < Settings->light_pixels; i++) { step_nr = i / Settings->light_step_pixels; - colorIndex = current_position - step_nr; - if(colorIndex < 0) colorIndex = 0; - if(colorIndex > scheme_count - 1) colorIndex = scheme_count - 1; + colorIndex = current_position - step_nr; + if (colorIndex < 0) { colorIndex = 0; } + if (colorIndex > scheme_count - 1) { colorIndex = scheme_count - 1; } c.R = mcolor[colorIndex].red; c.G = mcolor[colorIndex].green; c.B = mcolor[colorIndex].blue; // Adjust the scheme rotation - if(Settings->light_rotation & 0x02){ + if (Settings->light_rotation & 0x02) { strip->SetPixelColor(Settings->light_pixels - i - 1, c); } else { strip->SetPixelColor(i, c); From 25f23b24066f6fc9c407fd684f24ab8b8628e49d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 20 Nov 2021 14:37:12 +0100 Subject: [PATCH 073/185] Update changelogs --- CHANGELOG.md | 7 +++++++ RELEASENOTES.md | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf22faf1b..6d540abae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file. - Autoconfiguration for ESP32 and variants - ESP32 fix leftover GPIO configuration after restart - ESP32 Proof of Concept Sonoff SPM with limited functionality (switching and energy monitoring) (#13447) +- WS2812 scheme 13 stairs effect (#13595) - Preliminary support for Tasmota Apps (.tapp extesions) - Berry support for neopixel (WS2812, SK6812) @@ -16,6 +17,12 @@ All notable changes to this project will be documented in this file. - Removed ILI9488 driver in favor of Unversal Display Driver - IRremoteESP8266 library from v2.7.20 to v2.8.0 (#13738) +### Fixed +- ESP32 analog NTC temperature calculation (#13703) + +### Removed +- ILI9488 driver in favour of Universal Display driver (#13719) + ## [10.0.0.2] 20211113 ### Added - Support for HDC2010 temperature/humidity sensor by Luc Boudreau (#13633) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index c73e1da40..510875d72 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -107,6 +107,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo - ESP32 Proof of Concept Sonoff SPM with limited functionality (switching and energy monitoring) [#13447](https://github.com/arendst/Tasmota/issues/13447) - Command ``TcpConfig`` for TCPBridge protocol configuration [#13565](https://github.com/arendst/Tasmota/issues/13565) - Support for HDC2010 temperature/humidity sensor by Luc Boudreau [#13633](https://github.com/arendst/Tasmota/issues/13633) +- WS2812 scheme 13 stairs effect [#13595](https://github.com/arendst/Tasmota/issues/13595) ### Breaking Changed - ESP32-S2 TSettings memory usage fixed to 4096 bytes regression from v9.5.0.8 @@ -114,6 +115,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo ### Changed - ESP32 core library from v1.0.7.4 to v2.0.1 - ESP32-C3 core library from v2.0.0-post to v2.0.1 +- IRremoteESP8266 library from v2.7.20 to v2.8.0 - File editor no-wrap [#13427](https://github.com/arendst/Tasmota/issues/13427) - ESP8266 Gratuitous ARP enabled and set to 60 seconds [#13623](https://github.com/arendst/Tasmota/issues/13623) @@ -124,4 +126,8 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo - GUI checkbox MQTT TLS not saved regression from v9.2.0.3 [#13442](https://github.com/arendst/Tasmota/issues/13442) - Discovery of shutters [#13572](https://github.com/arendst/Tasmota/issues/13572) - ESP32-C3 OneWire as used by DS18x20 [#13583](https://github.com/arendst/Tasmota/issues/13583) +- ESP32 analog NTC temperature calculation [#13703](https://github.com/arendst/Tasmota/issues/13703) + +### Removed +- ILI9488 driver in favour of Universal Display driver [#13719](https://github.com/arendst/Tasmota/issues/13719) From efb77a65477f43441069195d18aece5b9afea61a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 20 Nov 2021 17:29:10 +0100 Subject: [PATCH 074/185] Rewrite Sonoff SPM state machine - Rewrite Sonoff SPM state machine for easier maintenance - Fix handling user output when initiating a scan --- tasmota/xdrv_86_esp32_sonoff_spm.ino | 154 ++++++++++++++++----------- 1 file changed, 89 insertions(+), 65 deletions(-) diff --git a/tasmota/xdrv_86_esp32_sonoff_spm.ino b/tasmota/xdrv_86_esp32_sonoff_spm.ino index f40c824fa..de2976d73 100644 --- a/tasmota/xdrv_86_esp32_sonoff_spm.ino +++ b/tasmota/xdrv_86_esp32_sonoff_spm.ino @@ -30,7 +30,7 @@ * Bulk of the action is handled by ARM processors present in every unit communicating over modbus RS-485. * Each SPM-4Relay has 4 bistable relays with their own CSE7761 energy monitoring device handled by an ARM processor. * Green led is controlled by ARM processor indicating SD-Card access. - * ESP32 is used as interface between Welink and ARM processor in SPM-Main unit communicating over proprietary serial protocol. + * ESP32 is used as interface between eWelink and ARM processor in SPM-Main unit communicating over proprietary serial protocol. * Inductive/Capacitive loads are not reported correctly. * Power on sequence for two SPM-4Relay modules is 00-00-15-10-(0F)-(13)-(13)-(19)-0C-09-04-09-04-0B-0B * @@ -124,10 +124,19 @@ #define SSPM_MODULE_NAME_SIZE 12 -enum SspmInitSteps { SPM_NONE, SPM_WAIT, SPM_RESET, SPM_POLL, SPM_POLL_ACK, SPM_SEND_FUNC_UNITS, SPM_STEP_WAIT2, - SPM_DEVICES_FOUND, - SPM_GET_ENERGY_TOTALS, - SPM_ALLOW_LOOP}; +enum SspmMachineStates { SPM_NONE, // Do nothing + SPM_WAIT, // Wait 100ms + SPM_RESET, // Toggle ARM reset pin + SPM_POLL_ARM, // Wait for first acknowledge from ARM after reset + SPM_POLL_ARM_2, // Wait for second acknowledge from ARM after reset + SPM_SEND_FUNC_UNITS, // Get number of units + SPM_START_SCAN, // Start module scan sequence + SPM_WAIT_FOR_SCAN, // Wait for scan sequence to complete + SPM_SCAN_COMPLETE, // Scan complete + SPM_GET_ENERGY_TOTALS, // Init available Energy totals registers + SPM_UPDATE_CHANNELS, // Update Energy for powered on channels + SPM_UPDATE_TOTALS // Update Energy totals for powered on channels + }; #include TasmotaSerial *SspmSerial; @@ -156,7 +165,7 @@ typedef struct { uint8_t counter; uint8_t command_sequence; uint8_t loop_step; - uint8_t init_step; + uint8_t mstate; uint8_t last_button; bool discovery_triggered; } TSspm; @@ -528,7 +537,7 @@ void SSPMHandleReceivedData(void) { |Er| |St| */ if ((1 == Sspm->expected_bytes) && (0 == SspmBuffer[19])) { - Sspm->init_step++; + Sspm->mstate++; // Cycle to } break; case SSPM_FUNC_GET_OPS: @@ -591,15 +600,14 @@ void SSPMHandleReceivedData(void) { } else { AddLog(LOG_LEVEL_DEBUG, PSTR("SPM: Relay scan done")); - Sspm->init_step = SPM_DEVICES_FOUND; -// Sspm->get_energy_relay = 1; -// Sspm->allow_updates = 1; // Enable requests from 100mSec loop + Sspm->mstate = SPM_SCAN_COMPLETE; } break; case SSPM_FUNC_SET_TIME: /* 0x0C AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 80 0c 00 01 00 04 3e 62 */ + TasmotaGlobal.devices_present = 0; SSPMSendGetModuleState(Sspm->module_selected -1); break; case SSPM_FUNC_INIT_SCAN: @@ -607,7 +615,6 @@ void SSPMHandleReceivedData(void) { 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 AA 55 01 ff ff ff ff ff ff ff ff ff ff ff ff 80 10 00 01 00 02 e5 03 */ - Sspm->module_max = 0; break; case SSPM_FUNC_UNITS: /* 0x15 @@ -615,7 +622,7 @@ void SSPMHandleReceivedData(void) { AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 80 15 00 04 00 01 00 00 01 81 b1 |?? ?? ?? ??| */ - SSPMSendInitScan(); + Sspm->mstate = SPM_START_SCAN; break; case SSPM_FUNC_GET_ENERGY_TOTAL: /* 0x16 @@ -746,7 +753,6 @@ void SSPMHandleReceivedData(void) { /* 0x0F AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 0f 00 01 02 01 9d f8 */ -// Sspm->module_max = 0; SSPMSendAck(command_sequence); break; case SSPM_FUNC_SCAN_RESULT: @@ -851,7 +857,7 @@ void SSPMInit(void) { } Sspm->old_power = TasmotaGlobal.power; - Sspm->init_step = SPM_WAIT; // Start init sequence + Sspm->mstate = SPM_WAIT; // Start init sequence } void SSPMEvery100ms(void) { @@ -865,17 +871,18 @@ void SSPMEvery100ms(void) { } // Fix race condition if the ARM doesn't respond - if ((Sspm->init_step > SPM_NONE) && (Sspm->init_step < SPM_SEND_FUNC_UNITS)) { + if ((Sspm->mstate > SPM_NONE) && (Sspm->mstate < SPM_SEND_FUNC_UNITS)) { Sspm->counter++; if (Sspm->counter > 20) { - Sspm->init_step = SPM_NONE; + Sspm->mstate = SPM_NONE; } } - switch (Sspm->init_step) { + switch (Sspm->mstate) { case SPM_NONE: return; case SPM_WAIT: - Sspm->init_step++; + // 100ms wait + Sspm->mstate = SPM_RESET; break; case SPM_RESET: // Reset ARM @@ -883,22 +890,34 @@ void SSPMEvery100ms(void) { delay(18); digitalWrite(SSPM_GPIO_ARM_RESET, 1); delay(18); - Sspm->init_step++; - case SPM_POLL: + Sspm->mstate = SPM_POLL_ARM; + case SPM_POLL_ARM: + // Wait for first acknowledge from ARM after reset SSPMSendCmnd(SSPM_FUNC_FIND); break; - case SPM_POLL_ACK: + case SPM_POLL_ARM_2: + // Wait for second acknowledge from ARM after reset SSPMSendCmnd(SSPM_FUNC_FIND); break; case SPM_SEND_FUNC_UNITS: - Sspm->init_step++; + // Get number of units SSPMSendCmnd(SSPM_FUNC_UNITS); break; - case SPM_DEVICES_FOUND: - TasmotaGlobal.discovery_counter = 1; // force TasDiscovery() + case SPM_START_SCAN: + // Start scan module sequence + Sspm->module_max = 0; + SSPMSendInitScan(); + Sspm->mstate = SPM_WAIT_FOR_SCAN; + break; + case SPM_WAIT_FOR_SCAN: + // Wait for scan sequence to complete + break; + case SPM_SCAN_COMPLETE: + // Scan sequence finished + TasmotaGlobal.discovery_counter = 1; // Force TasDiscovery() Sspm->get_energy_relay = 1; - Sspm->allow_updates = 1; // Enable requests from 100mSec loop - Sspm->init_step++; + Sspm->allow_updates = 1; // Enable requests from 100mSec loop + Sspm->mstate = SPM_GET_ENERGY_TOTALS; break; case SPM_GET_ENERGY_TOTALS: // Retrieve Energy total status from up to 128 relays @@ -908,47 +927,54 @@ void SSPMEvery100ms(void) { Sspm->get_energy_relay++; if (Sspm->get_energy_relay > TasmotaGlobal.devices_present) { Sspm->get_energy_relay = 1; - Sspm->init_step++; + Sspm->mstate = SPM_UPDATE_CHANNELS; } } break; - case SPM_ALLOW_LOOP: - // Retrieve Energy status from up to 128 relays + case SPM_UPDATE_CHANNELS: + // Retrieve Energy status from up to 128 powered on relays if (Sspm->allow_updates && (Sspm->get_energy_relay > 0)) { power_t powered_on = TasmotaGlobal.power >> (Sspm->get_energy_relay -1); - if (0 == Sspm->loop_step) { - // Get energy total only once in any 256 requests to safe comms - if (powered_on &1) { - SSPMSetLock(4); - SSPMSendGetEnergyTotal(Sspm->get_energy_relay -1); - } - Sspm->get_energy_relay++; - if (Sspm->get_energy_relay > TasmotaGlobal.devices_present) { - Sspm->get_energy_relay = 1; - Sspm->loop_step++; - } + if (powered_on &1) { + SSPMSetLock(4); + SSPMSendGetEnergy(Sspm->get_energy_relay -1); } else { - if (powered_on &1) { - SSPMSetLock(4); - SSPMSendGetEnergy(Sspm->get_energy_relay -1); - } else { - uint32_t relay_set = (Sspm->get_energy_relay -1) >> 2; - uint32_t relay_num = (Sspm->get_energy_relay -1) &3; - if (Sspm->voltage[relay_set][relay_num]) { - Sspm->voltage[relay_set][relay_num] = 0; - Sspm->current[relay_set][relay_num] = 0; - Sspm->active_power[relay_set][relay_num] = 0; - Sspm->apparent_power[relay_set][relay_num] = 0; - Sspm->reactive_power[relay_set][relay_num] = 0; - Sspm->power_factor[relay_set][relay_num] = 0; - } - } - Sspm->loop_step++; // Rolls over after 256 so allows for scanning at least all relays twice - Sspm->get_energy_relay++; - if ((Sspm->get_energy_relay > TasmotaGlobal.devices_present) || !Sspm->loop_step) { - Sspm->get_energy_relay = 1; + uint32_t relay_set = (Sspm->get_energy_relay -1) >> 2; + uint32_t relay_num = (Sspm->get_energy_relay -1) &3; + if (Sspm->voltage[relay_set][relay_num]) { + Sspm->voltage[relay_set][relay_num] = 0; + Sspm->current[relay_set][relay_num] = 0; + Sspm->active_power[relay_set][relay_num] = 0; + Sspm->apparent_power[relay_set][relay_num] = 0; + Sspm->reactive_power[relay_set][relay_num] = 0; + Sspm->power_factor[relay_set][relay_num] = 0; } } + Sspm->get_energy_relay++; + if (Sspm->get_energy_relay > TasmotaGlobal.devices_present) { + Sspm->get_energy_relay = 1; + } + Sspm->loop_step++; // Rolls over after 256 so allows for scanning at least all relays twice + if (!Sspm->loop_step) { + Sspm->get_energy_relay = 1; + Sspm->mstate = SPM_UPDATE_TOTALS; + } + } + break; + case SPM_UPDATE_TOTALS: + // Retrieve Energy totals from up to 128 powered on relays + if (Sspm->allow_updates && (Sspm->get_energy_relay > 0)) { + power_t powered_on = TasmotaGlobal.power >> (Sspm->get_energy_relay -1); + // Get energy total only once in any 256 requests to safe comms + if (powered_on &1) { + SSPMSetLock(4); + SSPMSendGetEnergyTotal(Sspm->get_energy_relay -1); + } + Sspm->get_energy_relay++; + if (Sspm->get_energy_relay > TasmotaGlobal.devices_present) { + Sspm->get_energy_relay = 1; + Sspm->mstate = SPM_UPDATE_CHANNELS; + } } break; } @@ -973,7 +999,7 @@ bool SSPMButton(void) { bool result = false; uint32_t button = XdrvMailbox.payload; if ((PRESSED == button) && (NOT_PRESSED == Sspm->last_button)) { // Button pressed - SSPMSendInitScan(); + Sspm->mstate = SPM_START_SCAN; result = true; // Disable further button processing } Sspm->last_button = button; @@ -1025,10 +1051,9 @@ void SSPMEnergyShow(bool json) { ResponseAppend_P(PSTR("]}")); } else { Sspm->rotate++; - if ((Sspm->rotate >> 2) == Sspm->module_max) { + if (Sspm->rotate >= TasmotaGlobal.devices_present) { Sspm->rotate = 0; } - uint32_t module = Sspm->rotate >> 2; uint32_t relay_base = module * 4; WSContentSend_P(PSTR("{s}" D_SENSOR_RELAY "{m}L%02d / L%02d / L%02d / L%02d{e}"), relay_base +1, relay_base +2, relay_base +3, relay_base +4); @@ -1077,9 +1102,8 @@ void CmndSSPMEnergyHistory(void) { } void CmndSSPMScan(void) { - SSPMSendInitScan(); - - ResponseCmndDone(); + Sspm->mstate = SPM_START_SCAN; + ResponseCmndChar(PSTR(D_JSON_STARTED)); } /*********************************************************************************************\ From 235bf403c69a2f9925da3565c49efae85d2050de Mon Sep 17 00:00:00 2001 From: Barbudor Date: Sat, 20 Nov 2021 22:35:07 +0100 Subject: [PATCH 075/185] add IfxPeriod --- tasmota/settings.h | 3 ++- tasmota/xdrv_59_influxdb.ino | 23 +++++++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index 99a226cba..c75842aac 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -598,7 +598,8 @@ typedef struct { int8_t shutter_tilt_config[5][MAX_SHUTTERS]; //508 int8_t shutter_tilt_pos[MAX_SHUTTERS]; //51C - uint8_t free_520[12]; // 520 + uint16_t influxdb_period; // 520 + uint8_t free_522[10]; // 522 uint16_t mqtt_keepalive; // 52C uint16_t mqtt_socket_timeout; // 52E diff --git a/tasmota/xdrv_59_influxdb.ino b/tasmota/xdrv_59_influxdb.ino index ecafe8003..13e50cbb6 100644 --- a/tasmota/xdrv_59_influxdb.ino +++ b/tasmota/xdrv_59_influxdb.ino @@ -37,6 +37,7 @@ * IfxBucket - Set Influxdb v2 and bucket name * IfxOrg - Set Influxdb v2 and organization * IfxToken - Set Influxdb v2 and token + * IfxPeriod - Set Influxdb period. If not set (or 0), use Teleperiod * * Set influxdb update interval with command teleperiod * @@ -364,8 +365,9 @@ void InfluxDbPublishPowerState(uint32_t device) { void InfluxDbLoop(void) { if (!TasmotaGlobal.global_state.network_down) { IFDB.interval--; - if (IFDB.interval <= 0 || IFDB.interval > Settings->tele_period) { - IFDB.interval = Settings->tele_period; + uint16_t period = Settings->influxdb_period ? Settings->influxdb_period : Settings->tele_period; + if (IFDB.interval <= 0 || IFDB.interval > period) { + IFDB.interval = period; if (!IFDB.init) { if (InfluxDbParameterInit()) { IFDB.init = InfluxDbValidateConnection(); @@ -408,20 +410,23 @@ void InfluxDbLoop(void) { #define D_CMND_INFLUXDBTOKEN "Token" #define D_CMND_INFLUXDBDATABASE "Database" #define D_CMND_INFLUXDBBUCKET "Bucket" +#define D_CMND_INFLUXDBPERIOD "Period" const char kInfluxDbCommands[] PROGMEM = D_PRFX_INFLUXDB "|" // Prefix "|" D_CMND_INFLUXDBLOG "|" D_CMND_INFLUXDBHOST "|" D_CMND_INFLUXDBPORT "|" D_CMND_INFLUXDBUSER "|" D_CMND_INFLUXDBORG "|" D_CMND_INFLUXDBPASSWORD "|" D_CMND_INFLUXDBTOKEN "|" - D_CMND_INFLUXDBDATABASE "|" D_CMND_INFLUXDBBUCKET; + D_CMND_INFLUXDBDATABASE "|" D_CMND_INFLUXDBBUCKET "|" + D_CMND_INFLUXDBPERIOD; void (* const InfluxCommand[])(void) PROGMEM = { &CmndInfluxDbState, &CmndInfluxDbLog, &CmndInfluxDbHost, &CmndInfluxDbPort, &CmndInfluxDbUser, &CmndInfluxDbUser, &CmndInfluxDbPassword, &CmndInfluxDbPassword, - &CmndInfluxDbDatabase, &CmndInfluxDbDatabase }; + &CmndInfluxDbDatabase, &CmndInfluxDbDatabase, + &CmndInfluxDbPeriod }; void InfluxDbReinit(void) { IFDB.init = false; @@ -504,6 +509,16 @@ void CmndInfluxDbDatabase(void) { ResponseCmndChar(SettingsText(SET_INFLUXDB_BUCKET)); } +void CmndInfluxDbPeriod(void) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings->influxdb_period = XdrvMailbox.payload; + if(Settings->influxdb_period > 0 && Settings->influxdb_period < 10) { + Settings->influxdb_period = 10; + } + } + ResponseCmndNumber(Settings->influxdb_period); +} + /*********************************************************************************************\ * Interface \*********************************************************************************************/ From ced7aa5a084192737364649b28a7c23a1959abbb Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 21 Nov 2021 13:30:05 +0100 Subject: [PATCH 076/185] Fix ESP32 ethernet broken by core 2.x - Fix ESP32 ethernet broken by core 2.x - Change ethernet hostname ending in ``_eth`` to ``-eth`` according to RFC952 --- CHANGELOG.md | 3 +++ RELEASENOTES.md | 2 ++ tasmota/xdrv_82_esp32_ethernet.ino | 16 ++++++++-------- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d540abae..3a53c17c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,14 +11,17 @@ All notable changes to this project will be documented in this file. - WS2812 scheme 13 stairs effect (#13595) - Preliminary support for Tasmota Apps (.tapp extesions) - Berry support for neopixel (WS2812, SK6812) +- Command ``IfxPeriod `` to overrule ``Teleperiod`` for Influx messages (#13750) ### Changed - ESP8266 Gratuitous ARP enabled and set to 60 seconds (#13623) - Removed ILI9488 driver in favor of Unversal Display Driver - IRremoteESP8266 library from v2.7.20 to v2.8.0 (#13738) +- Ethernet hostname ending in ``_eth`` to ``-eth`` according to RFC952 ### Fixed - ESP32 analog NTC temperature calculation (#13703) +- ESP32 ethernet broken by core 2.x ### Removed - ILI9488 driver in favour of Universal Display driver (#13719) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 510875d72..985262bd6 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -108,6 +108,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo - Command ``TcpConfig`` for TCPBridge protocol configuration [#13565](https://github.com/arendst/Tasmota/issues/13565) - Support for HDC2010 temperature/humidity sensor by Luc Boudreau [#13633](https://github.com/arendst/Tasmota/issues/13633) - WS2812 scheme 13 stairs effect [#13595](https://github.com/arendst/Tasmota/issues/13595) +- Command ``IfxPeriod `` to overrule ``Teleperiod`` for Influx messages [#13750](https://github.com/arendst/Tasmota/issues/13750) ### Breaking Changed - ESP32-S2 TSettings memory usage fixed to 4096 bytes regression from v9.5.0.8 @@ -118,6 +119,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo - IRremoteESP8266 library from v2.7.20 to v2.8.0 - File editor no-wrap [#13427](https://github.com/arendst/Tasmota/issues/13427) - ESP8266 Gratuitous ARP enabled and set to 60 seconds [#13623](https://github.com/arendst/Tasmota/issues/13623) +- Ethernet hostname ending in ``_eth`` to ``-eth`` according to RFC952 ### Fixed - Initial reset RTC memory based variables like EnergyToday and EnergyTotal diff --git a/tasmota/xdrv_82_esp32_ethernet.ino b/tasmota/xdrv_82_esp32_ethernet.ino index d276ad7fd..1deb646b5 100644 --- a/tasmota/xdrv_82_esp32_ethernet.ino +++ b/tasmota/xdrv_82_esp32_ethernet.ino @@ -86,15 +86,15 @@ char eth_hostname[sizeof(TasmotaGlobal.hostname)]; void EthernetEvent(WiFiEvent_t event) { switch (event) { - case SYSTEM_EVENT_ETH_START: + case ARDUINO_EVENT_ETH_START: AddLog(LOG_LEVEL_DEBUG, PSTR("ETH: " D_ATTEMPTING_CONNECTION)); ETH.setHostname(eth_hostname); break; - case SYSTEM_EVENT_ETH_CONNECTED: + case ARDUINO_EVENT_ETH_CONNECTED: AddLog(LOG_LEVEL_INFO, PSTR("ETH: " D_CONNECTED " at %dMbps%s"), ETH.linkSpeed(), (ETH.fullDuplex()) ? " Full Duplex" : ""); break; - case SYSTEM_EVENT_ETH_GOT_IP: + case ARDUINO_EVENT_ETH_GOT_IP: AddLog(LOG_LEVEL_DEBUG, PSTR("ETH: Mac %s, IPAddress %_I, Hostname %s"), ETH.macAddress().c_str(), (uint32_t)ETH.localIP(), eth_hostname); Settings->ipv4_address[1] = (uint32_t)ETH.gatewayIP(); @@ -103,11 +103,11 @@ void EthernetEvent(WiFiEvent_t event) { Settings->ipv4_address[4] = (uint32_t)ETH.dnsIP(1); TasmotaGlobal.global_state.eth_down = 0; break; - case SYSTEM_EVENT_ETH_DISCONNECTED: + case ARDUINO_EVENT_ETH_DISCONNECTED: AddLog(LOG_LEVEL_INFO, PSTR("ETH: Disconnected")); TasmotaGlobal.global_state.eth_down = 1; break; - case SYSTEM_EVENT_ETH_STOP: + case ARDUINO_EVENT_ETH_STOP: AddLog(LOG_LEVEL_DEBUG, PSTR("ETH: Stopped")); TasmotaGlobal.global_state.eth_down = 1; break; @@ -129,9 +129,9 @@ void EthernetInit(void) { Settings->eth_clk_mode = ETH_CLOCK_GPIO0_IN; // EthClockMode } -// snprintf_P(Eth.hostname, sizeof(Eth.hostname), PSTR("%s_eth"), TasmotaGlobal.hostname); - strlcpy(eth_hostname, TasmotaGlobal.hostname, sizeof(eth_hostname) -5); // Make sure there is room for "_eth" - strcat(eth_hostname, "_eth"); +// snprintf_P(Eth.hostname, sizeof(Eth.hostname), PSTR("%s-eth"), TasmotaGlobal.hostname); + strlcpy(eth_hostname, TasmotaGlobal.hostname, sizeof(eth_hostname) -5); // Make sure there is room for "-eth" + strcat(eth_hostname, "-eth"); WiFi.onEvent(EthernetEvent); From 366ee8f2636364e857eb00ca12b43e3e4d0bec17 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 21 Nov 2021 13:53:03 +0100 Subject: [PATCH 077/185] Odroid --- platformio_tasmota_env32.ini | 5 ++--- tasmota/tasmota_configurations_ESP32.h | 15 ++++++++++----- tasmota/xdrv_55_touch.ino | 12 ++++++++---- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/platformio_tasmota_env32.ini b/platformio_tasmota_env32.ini index b41146635..b67f4c90a 100644 --- a/platformio_tasmota_env32.ini +++ b/platformio_tasmota_env32.ini @@ -61,13 +61,12 @@ lib_extra_dirs = lib/libesp32 [env:tasmota32-odroidgo] extends = env:tasmota32_base board = esp32-odroid -build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_ODROID_GO -lib_extra_dirs = lib/libesp32, lib/lib_basic, lib/lib_i2c, lib/lib_rf, lib/lib_div, lib/lib_ssl, lib/lib_display +build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_ODROID_GO -DUSE_UNIVERSAL_DISPLAY -DUSE_AUTOCONF [env:tasmota32-core2] extends = env:tasmota32_base board = esp32-m5core2 -build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_M5STACK_CORE2 -DUSE_UNIVERSAL_DISPLAY +build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_M5STACK_CORE2 -DUSE_UNIVERSAL_DISPLAY -DUSE_AUTOCONF lib_extra_dirs = lib/libesp32, lib/libesp32_lvgl, lib/lib_basic, lib/lib_i2c, lib/lib_rf, lib/lib_div, lib/lib_ssl, lib/lib_display, lib/lib_audio [env:tasmota32-bluetooth] diff --git a/tasmota/tasmota_configurations_ESP32.h b/tasmota/tasmota_configurations_ESP32.h index b708201d7..b358d74e0 100644 --- a/tasmota/tasmota_configurations_ESP32.h +++ b/tasmota/tasmota_configurations_ESP32.h @@ -75,13 +75,18 @@ #undef USE_HOME_ASSISTANT -#define USE_ADC +#define USE_I2C #define USE_SPI - #define USE_DISPLAY // Add SPI Display Support (+2k code) + #define USE_DISPLAY #define SHOW_SPLASH - #ifndef USE_UNIVERSAL_DISPLAY - #define USE_DISPLAY_ILI9341 // [DisplayModel 4] Enable ILI9341 Tft 480x320 display (+19k code) - #endif +#ifdef USE_UNIVERSAL_DISPLAY + #define USE_LVGL + #define USE_LVGL_FREETYPE +// #define USE_DISPLAY_LVGL_ONLY +#else + #define USE_DISPLAY_ILI9341 // [DisplayModel 4] Enable ILI9341 Tft 480x320 display (+19k code) + #define USE_DISPLAY_MODES1TO5 +#endif //#define USE_BLE_ESP32 // Enable new BLE driver //#define USE_MI_ESP32 // (ESP32 only) Add support for ESP32 as a BLE-bridge (+9k2 mem, +292k flash) #endif // FIRMWARE_ODROID_GO diff --git a/tasmota/xdrv_55_touch.ino b/tasmota/xdrv_55_touch.ino index 4abb9683e..5453176bc 100644 --- a/tasmota/xdrv_55_touch.ino +++ b/tasmota/xdrv_55_touch.ino @@ -21,9 +21,9 @@ #if defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_LILYGO47) || defined(USE_TOUCH_BUTTONS) -// #ifdef USE_DISPLAY_LVGL_ONLY -// #undef USE_TOUCH_BUTTONS -// #endif +#ifdef USE_DISPLAY_LVGL_ONLY +#undef USE_TOUCH_BUTTONS +#endif #include @@ -317,5 +317,9 @@ bool Xdrv55(uint8_t function) { } return result; } - +#else +// dummy for LVGL without a touch controller +uint32_t Touch_Status(uint32_t sel) { +return 0; +} #endif // USE_TOUCH From 010f8f8d37a9820d3eb38d7a236a73fa7bc6ad95 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 21 Nov 2021 14:15:38 +0100 Subject: [PATCH 078/185] Add ethernet support to Sonoff SPM - Add ethernet support to Sonoff SPM - Update template to "Sonoff SPM (POC2)" (#13447) --- tasmota/xdrv_86_esp32_sonoff_spm.ino | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/tasmota/xdrv_86_esp32_sonoff_spm.ino b/tasmota/xdrv_86_esp32_sonoff_spm.ino index de2976d73..3a2e1166a 100644 --- a/tasmota/xdrv_86_esp32_sonoff_spm.ino +++ b/tasmota/xdrv_86_esp32_sonoff_spm.ino @@ -24,7 +24,10 @@ /*********************************************************************************************\ * Sonoff Stackable Power Manager (Current state: PROOF OF CONCEPT) * + * Initial POC template: * {"NAME":"Sonoff SPM (POC1)","GPIO":[1,1,1,1,3200,1,1,1,1,1,1,1,3232,1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,544,1,1,32,1,0,0,1],"FLAG":0,"BASE":1} + * Add ethernet support: + * {"NAME":"Sonoff SPM (POC2)","GPIO":[1,0,1,0,3200,5536,0,0,1,1,1,0,3232,0,5600,0,0,0,0,5568,0,0,0,0,0,0,0,0,544,1,1,32,1,0,0,1],"FLAG":0,"BASE":1} * * Things to know: * Bulk of the action is handled by ARM processors present in every unit communicating over modbus RS-485. @@ -40,8 +43,10 @@ * Button on SPM-Main initiates re-scan of SPM-4Relay units. * Blue led equals Tasmota WiFi status. * + * Tasmota POC2: + * Ethernet support. + * * Todo: - * Ethernet support (Find correct MDIO, MDC, POWER GPIO's and ETH_ parameters). * Gui optimization for energy display. * Gui for Overload Protection entry (is handled by ARM processor). * Gui for Scheduling entry (is handled by ARM processor). @@ -56,26 +61,26 @@ * GPIO01 - Serial console TX (921600bps8N1 originally) * GPIO03 - Serial console RX * GPIO04 - ARM processor TX (115200bps8N1) + * GPIO05 - ETH POWER * GPIO12 - SPI MISO ARM pulsetrain code (input?) * GPIO13 - SPI CLK * GPIO14 - SPI CS ARM pulsetrain eoc (input?) * GPIO15 - ARM reset (output) - 18ms low active 125ms after restart esp32 * GPIO16 - ARM processor RX * GPIO17 - EMAC_CLK_OUT_180 - * GPIO18 - ??ETH MDIO + * GPIO18 - ETH MDIO * GPIO19 - EMAC_TXD0(RMII) * GPIO21 - EMAC_TX_EN(RMII) * GPIO22 - EMAC_TXD1(RMII) - * GPIO23 - ??ETH MDC + * GPIO23 - ETH MDC * GPIO25 - EMAC_RXD0(RMII) * GPIO26 - EMAC_RXD1(RMII) * GPIO27 - EMAC_RX_CRS_DV - * GPIO?? - ??ETH POWER * GPIO32 - Blue status led2 * GPIO33 - Yellow error led3 * GPIO35 - Button * #define ETH_TYPE ETH_PHY_LAN8720 - * #define ETH_CLKMODE ETH_CLOCK_GPIO0_IN + * #define ETH_CLKMODE ETH_CLOCK_GPIO17_OUT * #define ETH_ADDRESS 0 * * Variables used: @@ -103,7 +108,6 @@ #define SSPM_FUNC_GET_ENERGY_TOTAL 22 // 0x16 #define SSPM_FUNC_GET_ENERGY 24 // 0x18 #define SSPM_FUNC_GET_LOG 26 // 0x1A - #define SSPM_FUNC_ENERGY_PERIOD 27 // 0x1B // Receive @@ -829,7 +833,8 @@ void SSPMSerialInput(void) { } void SSPMInit(void) { - if (!ValidTemplate(PSTR("Sonoff SPM (POC1)"))) { return; } + if (!ValidTemplate(PSTR("Sonoff SPM (POC1)")) && + !ValidTemplate(PSTR("Sonoff SPM (POC2)"))) { return; } if (!PinUsed(GPIO_RXD) || !PinUsed(GPIO_TXD)) { return; } Sspm = (TSspm*)calloc(sizeof(TSspm), 1); @@ -856,6 +861,14 @@ void SSPMInit(void) { Settings->flag2.energy_resolution = 0; // SPM has no decimals on total energy } +#if CONFIG_IDF_TARGET_ESP32 +#ifdef USE_ETHERNET + Settings->eth_address = 0; // EthAddress + Settings->eth_type = ETH_PHY_LAN8720; // EthType + Settings->eth_clk_mode = ETH_CLOCK_GPIO17_OUT; // EthClockMode +#endif +#endif + Sspm->old_power = TasmotaGlobal.power; Sspm->mstate = SPM_WAIT; // Start init sequence } From 116da1f5d28d10e2759c171303173bc90f4b2954 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 21 Nov 2021 14:32:57 +0100 Subject: [PATCH 079/185] Fix SPM JSON Energy Total values --- tasmota/xdrv_86_esp32_sonoff_spm.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_86_esp32_sonoff_spm.ino b/tasmota/xdrv_86_esp32_sonoff_spm.ino index 3a2e1166a..f2d83439e 100644 --- a/tasmota/xdrv_86_esp32_sonoff_spm.ino +++ b/tasmota/xdrv_86_esp32_sonoff_spm.ino @@ -1039,7 +1039,7 @@ void SSPMEnergyShow(bool json) { if (json) { ResponseAppend_P(PSTR(",\"SPM\":{\"" D_JSON_TOTAL "\":[")); for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { - ResponseAppend_P(PSTR("%s%*_f"), (i>0)?",":"", 0, &Sspm->total[i >>2][i &3]); + ResponseAppend_P(PSTR("%s%*_f"), (i>0)?",":"", -1, &Sspm->total[i >>2][i &3]); } ResponseAppend_P(PSTR("],\"" D_JSON_POWERUSAGE "\":[")); for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { From 304f3399d628182e9070368481b75a0019d5b7b2 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 21 Nov 2021 15:12:09 +0100 Subject: [PATCH 080/185] add comment for corresponding if --- tasmota/xdrv_55_touch.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_55_touch.ino b/tasmota/xdrv_55_touch.ino index 5453176bc..269f775af 100644 --- a/tasmota/xdrv_55_touch.ino +++ b/tasmota/xdrv_55_touch.ino @@ -322,4 +322,4 @@ bool Xdrv55(uint8_t function) { uint32_t Touch_Status(uint32_t sel) { return 0; } -#endif // USE_TOUCH +#endif // #if defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_LILYGO47) || defined(USE_TOUCH_BUTTONS) From cb0ad2c75b93530c671498219c715bd3b6176f6e Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sun, 21 Nov 2021 18:54:13 +0100 Subject: [PATCH 081/185] Berry tasmota.read_sensors() --- lib/libesp32/Berry/default/be_tasmotalib.c | 4 + lib/libesp32/Berry/generate/be_const_strtab.h | 1 + .../Berry/generate/be_const_strtab_def.h | 5 +- .../generate/be_fixed_be_class_tasmota.h | 149 +++++++++--------- tasmota/support_command.ino | 2 +- tasmota/support_tasmota.ino | 8 +- tasmota/xdrv_12_discovery.ino | 2 +- tasmota/xdrv_12_home_assistant.ino | 2 +- tasmota/xdrv_52_3_berry_tasmota.ino | 29 ++++ tasmota/xdrv_59_influxdb.ino | 2 +- tasmota/xsns_75_prometheus.ino | 2 +- 11 files changed, 121 insertions(+), 85 deletions(-) diff --git a/lib/libesp32/Berry/default/be_tasmotalib.c b/lib/libesp32/Berry/default/be_tasmotalib.c index a6d936766..cba138c5d 100644 --- a/lib/libesp32/Berry/default/be_tasmotalib.c +++ b/lib/libesp32/Berry/default/be_tasmotalib.c @@ -32,6 +32,8 @@ extern int l_scaleuint(bvm *vm); extern int l_logInfo(bvm *vm); extern int l_save(bvm *vm); +extern int l_read_sensors(bvm *vm); + extern int l_respCmnd(bvm *vm); extern int l_respCmndStr(bvm *vm); extern int l_respCmndDone(bvm *vm); @@ -2010,6 +2012,8 @@ class be_class_tasmota (scope: global, name: Tasmota) { log, func(l_logInfo) save, func(l_save) + read_sensors, func(l_read_sensors) + resp_cmnd, func(l_respCmnd) resp_cmnd_str, func(l_respCmndStr) resp_cmnd_done, func(l_respCmndDone) diff --git a/lib/libesp32/Berry/generate/be_const_strtab.h b/lib/libesp32/Berry/generate/be_const_strtab.h index 12a0ebefc..c6a7bf5ec 100644 --- a/lib/libesp32/Berry/generate/be_const_strtab.h +++ b/lib/libesp32/Berry/generate/be_const_strtab.h @@ -307,6 +307,7 @@ extern const bcstring be_const_str_SERIAL_8N1; extern const bcstring be_const_str_pi; extern const bcstring be_const_str_add_header; extern const bcstring be_const_str_list; +extern const bcstring be_const_str_read_sensors; extern const bcstring be_const_str_super; extern const bcstring be_const_str_has; extern const bcstring be_const_str___upper__; diff --git a/lib/libesp32/Berry/generate/be_const_strtab_def.h b/lib/libesp32/Berry/generate/be_const_strtab_def.h index 759cf6c02..e7e4bc0f2 100644 --- a/lib/libesp32/Berry/generate/be_const_strtab_def.h +++ b/lib/libesp32/Berry/generate/be_const_strtab_def.h @@ -306,7 +306,8 @@ be_define_const_str(AudioFileSource, "AudioFileSource", 2959980058u, 0, 15, &be_ be_define_const_str(SERIAL_8N1, "SERIAL_8N1", 2369297235u, 0, 10, &be_const_str_pi); be_define_const_str(pi, "pi", 1213090802u, 0, 2, NULL); be_define_const_str(add_header, "add_header", 927130612u, 0, 10, &be_const_str_list); -be_define_const_str(list, "list", 217798785u, 0, 4, &be_const_str_super); +be_define_const_str(list, "list", 217798785u, 0, 4, &be_const_str_read_sensors); +be_define_const_str(read_sensors, "read_sensors", 892689201u, 0, 12, &be_const_str_super); be_define_const_str(super, "super", 4152230356u, 0, 5, NULL); be_define_const_str(has, "has", 3988721635u, 0, 3, NULL); be_define_const_str(__upper__, "__upper__", 3612202883u, 0, 9, &be_const_str_exp); @@ -515,6 +516,6 @@ static const bstring* const m_string_table[] = { static const struct bconststrtab m_const_string_table = { .size = 163, - .count = 326, + .count = 327, .table = m_string_table }; diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_tasmota.h b/lib/libesp32/Berry/generate/be_fixed_be_class_tasmota.h index 6a5f58838..c24ab2782 100644 --- a/lib/libesp32/Berry/generate/be_fixed_be_class_tasmota.h +++ b/lib/libesp32/Berry/generate/be_fixed_be_class_tasmota.h @@ -1,88 +1,89 @@ #include "be_constobj.h" static be_define_const_map_slots(be_class_tasmota_map) { - { be_const_key(chars_in_string, 62), be_const_closure(chars_in_string_closure) }, - { be_const_key(publish, -1), be_const_func(l_publish) }, - { be_const_key(try_rule, 5), be_const_closure(try_rule_closure) }, - { be_const_key(_settings_ptr, -1), be_const_comptr(&Settings) }, - { be_const_key(get_free_heap, 43), be_const_func(l_getFreeHeap) }, - { be_const_key(eth, 55), be_const_func(l_eth) }, - { be_const_key(set_power, -1), be_const_func(l_setpower) }, - { be_const_key(exec_rules, -1), be_const_closure(exec_rules_closure) }, - { be_const_key(i2c_enabled, -1), be_const_func(l_i2cenabled) }, - { be_const_key(event, -1), be_const_closure(event_closure) }, - { be_const_key(hs2rgb, -1), be_const_closure(hs2rgb_closure) }, - { be_const_key(time_str, 56), be_const_closure(time_str_closure) }, - { be_const_key(gen_cb, -1), be_const_closure(gen_cb_closure) }, - { be_const_key(response_append, 1), be_const_func(l_respAppend) }, - { be_const_key(set_light, -1), be_const_closure(set_light_closure) }, - { be_const_key(remove_driver, 47), be_const_closure(remove_driver_closure) }, - { be_const_key(yield, 37), be_const_func(l_yield) }, - { be_const_key(exec_cmd, 2), be_const_closure(exec_cmd_closure) }, - { be_const_key(rtc, 14), be_const_func(l_rtc) }, { be_const_key(cmd_res, -1), be_const_var(0) }, - { be_const_key(resp_cmnd_str, -1), be_const_func(l_respCmndStr) }, - { be_const_key(set_timer, -1), be_const_closure(set_timer_closure) }, - { be_const_key(resp_cmnd_error, -1), be_const_func(l_respCmndError) }, - { be_const_key(exec_tele, -1), be_const_closure(exec_tele_closure) }, - { be_const_key(_global_def, -1), be_const_comptr(&be_tasmota_global_struct) }, - { be_const_key(global, 51), be_const_var(1) }, - { be_const_key(_global_addr, -1), be_const_comptr(&TasmotaGlobal) }, - { be_const_key(add_driver, 12), be_const_closure(add_driver_closure) }, - { be_const_key(_timers, 53), be_const_var(2) }, - { be_const_key(_cb, 71), be_const_var(3) }, - { be_const_key(resp_cmnd_failed, -1), be_const_func(l_respCmndFailed) }, - { be_const_key(remove_rule, 0), be_const_closure(remove_rule_closure) }, - { be_const_key(web_send, 9), be_const_func(l_webSend) }, - { be_const_key(resp_cmnd, -1), be_const_func(l_respCmnd) }, - { be_const_key(remove_timer, 10), be_const_closure(remove_timer_closure) }, - { be_const_key(memory, -1), be_const_func(l_memory) }, - { be_const_key(cb_dispatch, -1), be_const_closure(cb_dispatch_closure) }, - { be_const_key(wire2, -1), be_const_var(4) }, - { be_const_key(find_op, -1), be_const_closure(find_op_closure) }, - { be_const_key(resolvecmnd, -1), be_const_func(l_resolveCmnd) }, - { be_const_key(get_option, -1), be_const_func(l_getoption) }, - { be_const_key(kv, 65), be_const_closure(kv_closure) }, - { be_const_key(wire_scan, -1), be_const_closure(wire_scan_closure) }, - { be_const_key(get_light, -1), be_const_closure(get_light_closure) }, - { be_const_key(_cmd, -1), be_const_func(l_cmd) }, - { be_const_key(gc, -1), be_const_closure(gc_closure) }, - { be_const_key(get_power, -1), be_const_func(l_getpower) }, - { be_const_key(cmd, 60), be_const_closure(cmd_closure) }, - { be_const_key(time_dump, -1), be_const_func(l_time_dump) }, - { be_const_key(settings, -1), be_const_var(5) }, - { be_const_key(load, -1), be_const_closure(load_closure) }, - { be_const_key(arch, -1), be_const_func(l_arch) }, - { be_const_key(_ccmd, -1), be_const_var(6) }, - { be_const_key(_get_cb, -1), be_const_func(l_get_cb) }, - { be_const_key(find_key_i, 19), be_const_closure(find_key_i_closure) }, - { be_const_key(time_reached, -1), be_const_func(l_timereached) }, { be_const_key(run_deferred, -1), be_const_closure(run_deferred_closure) }, - { be_const_key(_settings_def, -1), be_const_comptr(&be_tasmota_settings_struct) }, - { be_const_key(save, 25), be_const_func(l_save) }, - { be_const_key(millis, -1), be_const_func(l_millis) }, - { be_const_key(web_send_decimal, -1), be_const_func(l_webSendDecimal) }, - { be_const_key(wire1, 72), be_const_var(7) }, - { be_const_key(delay, -1), be_const_func(l_delay) }, - { be_const_key(scale_uint, 50), be_const_func(l_scaleuint) }, - { be_const_key(get_switch, -1), be_const_func(l_getswitch) }, - { be_const_key(wifi, 38), be_const_func(l_wifi) }, - { be_const_key(publish_result, -1), be_const_func(l_publish_result) }, - { be_const_key(_drivers, -1), be_const_var(8) }, - { be_const_key(add_cmd, -1), be_const_closure(add_cmd_closure) }, - { be_const_key(strftime, -1), be_const_func(l_strftime) }, - { be_const_key(log, -1), be_const_func(l_logInfo) }, + { be_const_key(set_light, -1), be_const_closure(set_light_closure) }, + { be_const_key(_global_def, -1), be_const_comptr(&be_tasmota_global_struct) }, + { be_const_key(_timers, -1), be_const_var(1) }, + { be_const_key(try_rule, -1), be_const_closure(try_rule_closure) }, + { be_const_key(time_dump, -1), be_const_func(l_time_dump) }, + { be_const_key(_rules, 73), be_const_var(2) }, + { be_const_key(get_switch, 21), be_const_func(l_getswitch) }, + { be_const_key(get_option, -1), be_const_func(l_getoption) }, + { be_const_key(find_op, 4), be_const_closure(find_op_closure) }, + { be_const_key(wire1, -1), be_const_var(3) }, + { be_const_key(resp_cmnd_failed, 29), be_const_func(l_respCmndFailed) }, + { be_const_key(exec_cmd, -1), be_const_closure(exec_cmd_closure) }, + { be_const_key(gen_cb, -1), be_const_closure(gen_cb_closure) }, + { be_const_key(_cb, 57), be_const_var(4) }, + { be_const_key(hs2rgb, 71), be_const_closure(hs2rgb_closure) }, + { be_const_key(gc, -1), be_const_closure(gc_closure) }, + { be_const_key(kv, -1), be_const_closure(kv_closure) }, { be_const_key(add_rule, -1), be_const_closure(add_rule_closure) }, - { be_const_key(resp_cmnd_done, 74), be_const_func(l_respCmndDone) }, - { be_const_key(_rules, 16), be_const_var(9) }, - { be_const_key(remove_cmd, -1), be_const_closure(remove_cmd_closure) }, + { be_const_key(scale_uint, -1), be_const_func(l_scaleuint) }, + { be_const_key(global, -1), be_const_var(5) }, + { be_const_key(rtc, 0), be_const_func(l_rtc) }, + { be_const_key(get_power, -1), be_const_func(l_getpower) }, + { be_const_key(wd, -1), be_const_var(6) }, + { be_const_key(_settings_def, -1), be_const_comptr(&be_tasmota_settings_struct) }, + { be_const_key(resp_cmnd_error, -1), be_const_func(l_respCmndError) }, + { be_const_key(read_sensors, 56), be_const_func(l_read_sensors) }, + { be_const_key(settings, -1), be_const_var(7) }, + { be_const_key(chars_in_string, -1), be_const_closure(chars_in_string_closure) }, + { be_const_key(save, -1), be_const_func(l_save) }, + { be_const_key(set_timer, -1), be_const_closure(set_timer_closure) }, + { be_const_key(time_str, -1), be_const_closure(time_str_closure) }, + { be_const_key(response_append, 14), be_const_func(l_respAppend) }, + { be_const_key(remove_driver, -1), be_const_closure(remove_driver_closure) }, + { be_const_key(i2c_enabled, -1), be_const_func(l_i2cenabled) }, + { be_const_key(web_send_decimal, -1), be_const_func(l_webSendDecimal) }, + { be_const_key(load, -1), be_const_closure(load_closure) }, + { be_const_key(_settings_ptr, 55), be_const_comptr(&Settings) }, + { be_const_key(millis, 23), be_const_func(l_millis) }, + { be_const_key(event, 67), be_const_closure(event_closure) }, + { be_const_key(cmd, -1), be_const_closure(cmd_closure) }, + { be_const_key(publish_result, 60), be_const_func(l_publish_result) }, + { be_const_key(_drivers, -1), be_const_var(8) }, + { be_const_key(get_light, 1), be_const_closure(get_light_closure) }, { be_const_key(init, -1), be_const_closure(init_closure) }, - { be_const_key(wd, 52), be_const_var(10) }, + { be_const_key(remove_cmd, 24), be_const_closure(remove_cmd_closure) }, + { be_const_key(time_reached, -1), be_const_func(l_timereached) }, + { be_const_key(_cmd, 68), be_const_func(l_cmd) }, + { be_const_key(remove_timer, -1), be_const_closure(remove_timer_closure) }, + { be_const_key(remove_rule, 70), be_const_closure(remove_rule_closure) }, + { be_const_key(resolvecmnd, 41), be_const_func(l_resolveCmnd) }, + { be_const_key(web_send, 38), be_const_func(l_webSend) }, + { be_const_key(cb_dispatch, 6), be_const_closure(cb_dispatch_closure) }, + { be_const_key(memory, -1), be_const_func(l_memory) }, + { be_const_key(wire_scan, -1), be_const_closure(wire_scan_closure) }, + { be_const_key(strftime, 16), be_const_func(l_strftime) }, + { be_const_key(resp_cmnd_done, -1), be_const_func(l_respCmndDone) }, + { be_const_key(_get_cb, -1), be_const_func(l_get_cb) }, + { be_const_key(add_driver, -1), be_const_closure(add_driver_closure) }, + { be_const_key(exec_rules, -1), be_const_closure(exec_rules_closure) }, + { be_const_key(add_cmd, -1), be_const_closure(add_cmd_closure) }, + { be_const_key(find_key_i, -1), be_const_closure(find_key_i_closure) }, + { be_const_key(log, 40), be_const_func(l_logInfo) }, + { be_const_key(wire2, -1), be_const_var(9) }, + { be_const_key(get_free_heap, -1), be_const_func(l_getFreeHeap) }, + { be_const_key(resp_cmnd_str, -1), be_const_func(l_respCmndStr) }, + { be_const_key(set_power, -1), be_const_func(l_setpower) }, + { be_const_key(delay, -1), be_const_func(l_delay) }, + { be_const_key(wifi, -1), be_const_func(l_wifi) }, + { be_const_key(yield, -1), be_const_func(l_yield) }, + { be_const_key(arch, -1), be_const_func(l_arch) }, + { be_const_key(resp_cmnd, 69), be_const_func(l_respCmnd) }, + { be_const_key(_global_addr, 26), be_const_comptr(&TasmotaGlobal) }, + { be_const_key(publish, -1), be_const_func(l_publish) }, + { be_const_key(_ccmd, -1), be_const_var(10) }, + { be_const_key(eth, -1), be_const_func(l_eth) }, + { be_const_key(exec_tele, -1), be_const_closure(exec_tele_closure) }, }; static be_define_const_map( be_class_tasmota_map, - 77 + 78 ); BE_EXPORT_VARIABLE be_define_const_class( diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 3daea88a7..23cd04c0b 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -621,7 +621,7 @@ void CmndStatus(void) if ((0 == payload) || (8 == payload) || (10 == payload)) { Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS10_SENSOR "\":")); - MqttShowSensor(); + MqttShowSensor(true); ResponseJsonEnd(); CmndStatusResponse((8 == payload) ? 8 : 10); } diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index bfe894446..76db6006f 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -835,7 +835,7 @@ String GetSwitchText(uint32_t i) { return switch_text; } -bool MqttShowSensor(void) +bool MqttShowSensor(bool call_show_sensor) { ResponseAppendTime(); @@ -894,20 +894,20 @@ bool MqttShowSensor(void) } ResponseJsonEnd(); - if (json_data_available) { XdrvCall(FUNC_SHOW_SENSOR); } + if (call_show_sensor && json_data_available) { XdrvCall(FUNC_SHOW_SENSOR); } return json_data_available; } void MqttPublishSensor(void) { ResponseClear(); - if (MqttShowSensor()) { + if (MqttShowSensor(true)) { MqttPublishTeleSensor(); } } void MqttPublishTeleperiodSensor(void) { ResponseClear(); - if (MqttShowSensor()) { + if (MqttShowSensor(true)) { MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings->flag.mqtt_sensor_retain); // CMND_SENSORRETAIN XdrvRulesProcess(1); } diff --git a/tasmota/xdrv_12_discovery.ino b/tasmota/xdrv_12_discovery.ino index 3ade73dbb..da92495d5 100644 --- a/tasmota/xdrv_12_discovery.ino +++ b/tasmota/xdrv_12_discovery.ino @@ -215,7 +215,7 @@ void TasDiscovery(void) { if (!Settings->flag.hass_discovery) { // SetOption19 - Clear retained message Response_P(PSTR("{\"sn\":")); - MqttShowSensor(); + MqttShowSensor(true); ResponseAppend_P(PSTR(",\"ver\":1}")); } snprintf_P(stopic, sizeof(stopic), PSTR("tasmota/discovery/%s/sensors"), NetworkUniqueId().c_str()); diff --git a/tasmota/xdrv_12_home_assistant.ino b/tasmota/xdrv_12_home_assistant.ino index efb7a253d..2ece432c7 100644 --- a/tasmota/xdrv_12_home_assistant.ino +++ b/tasmota/xdrv_12_home_assistant.ino @@ -382,7 +382,7 @@ void NewHAssDiscovery(void) { if (!Settings->flag.hass_discovery) { // SetOption19 - Clear retained message Response_P(PSTR("{\"sn\":")); - MqttShowSensor(); + MqttShowSensor(true); ResponseAppend_P(PSTR(",\"ver\":1}")); } snprintf_P(stopic, sizeof(stopic), PSTR("tasmota/discovery/%s/sensors"), NetworkUniqueId().c_str()); diff --git a/tasmota/xdrv_52_3_berry_tasmota.ino b/tasmota/xdrv_52_3_berry_tasmota.ino index 573298789..438bd69c1 100644 --- a/tasmota/xdrv_52_3_berry_tasmota.ino +++ b/tasmota/xdrv_52_3_berry_tasmota.ino @@ -541,6 +541,35 @@ extern "C" { } } +/*********************************************************************************************\ + * Native functions mapped to Berry functions + * + * read_sensors(show_sensor:bool) -> string + * +\*********************************************************************************************/ +extern "C" { + int32_t l_read_sensors(struct bvm *vm); + int32_t l_read_sensors(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + bool sensor_display = false; // don't trigger a display by default + if (top >= 2) { + sensor_display = be_tobool(vm, 2); + } + ResponseClear(); + if (MqttShowSensor(sensor_display)) { + // return string + be_pushstring(vm, ResponseData()); + be_return(vm); + } else { + be_return_nil(vm); + } + } +} + +/*********************************************************************************************\ + * Logging functions + * +\*********************************************************************************************/ // called as a replacement to Berry `print()` void berry_log(const char * berry_buf); void berry_log(const char * berry_buf) { diff --git a/tasmota/xdrv_59_influxdb.ino b/tasmota/xdrv_59_influxdb.ino index ecafe8003..3afb6ada8 100644 --- a/tasmota/xdrv_59_influxdb.ino +++ b/tasmota/xdrv_59_influxdb.ino @@ -385,7 +385,7 @@ void InfluxDbLoop(void) { // {"Time":"2021-08-14T17:19:33","Switch1":"ON","Switch2":"OFF","ANALOG":{"Temperature":184.72},"DS18B20":{"Id":"01144A0CB2AA","Temperature":27.50},"HTU21":{"Temperature":28.23,"Humidity":39.7,"DewPoint":13.20},"Global":{"Temperature":27.50,"Humidity":39.7,"DewPoint":12.55},"TempUnit":"C"} ResponseClear(); - if (MqttShowSensor()) { // Pull sensor data + if (MqttShowSensor(true)) { // Pull sensor data InfluxDbProcessJson(); }; diff --git a/tasmota/xsns_75_prometheus.ino b/tasmota/xsns_75_prometheus.ino index caa2330fa..df9d41881 100644 --- a/tasmota/xsns_75_prometheus.ino +++ b/tasmota/xsns_75_prometheus.ino @@ -282,7 +282,7 @@ void HandleMetrics(void) { } ResponseClear(); - MqttShowSensor(); //Pull sensor data + MqttShowSensor(true); //Pull sensor data String jsonStr = ResponseData(); JsonParser parser((char *)jsonStr.c_str()); JsonParserObject root = parser.getRootObject(); From e173f7492e406056301e7bdb289dbb9d33f06188 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sun, 21 Nov 2021 22:05:07 +0100 Subject: [PATCH 082/185] DisplayDimmer support for M5StickC --- tasmota/berry/drivers/i2c_axp192_M5StickC.be | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tasmota/berry/drivers/i2c_axp192_M5StickC.be b/tasmota/berry/drivers/i2c_axp192_M5StickC.be index 9d38bea3a..2d0c63d24 100644 --- a/tasmota/berry/drivers/i2c_axp192_M5StickC.be +++ b/tasmota/berry/drivers/i2c_axp192_M5StickC.be @@ -85,6 +85,19 @@ class AXP192_M5StickC : AXP192 def set_lcd_reset(state) self.set_ldo_enable(3, state) end + + # Dimmer in percentage + def set_displaydimmer(x) + var v = tasmota.scale_uint(x, 0, 100, 2500, 3300) + self.set_lcd_voltage(v) + end + + # respond to display events + def display(cmd, idx, payload, raw) + if cmd == "dim" || cmd == "power" + self.set_displaydimmer(idx) + end + end end axp = AXP192_M5StickC() From 871baa7f4172f4487a4e9de1c6f50591bdd36b20 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sun, 21 Nov 2021 23:08:54 +0100 Subject: [PATCH 083/185] Berry remove warning when no debug --- lib/libesp32/Berry/default/be_tasmotalib.c | 221 ++-- .../Berry/default/embedded/Tasmota.be | 19 +- lib/libesp32/Berry/generate/be_const_strtab.h | 677 +++++------ .../Berry/generate/be_const_strtab_def.h | 1008 +++++++++-------- .../generate/be_fixed_be_class_tasmota.h | 151 +-- lib/libesp32/Berry/src/be_constobj.h | 7 + lib/libesp32/Berry/src/be_solidifylib.c | 7 +- 7 files changed, 1065 insertions(+), 1025 deletions(-) diff --git a/lib/libesp32/Berry/default/be_tasmotalib.c b/lib/libesp32/Berry/default/be_tasmotalib.c index cba138c5d..76720b7b4 100644 --- a/lib/libesp32/Berry/default/be_tasmotalib.c +++ b/lib/libesp32/Berry/default/be_tasmotalib.c @@ -143,24 +143,26 @@ be_local_closure(init, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[13]) { /* constants */ - /* K0 */ be_nested_string("global", 503252654, 6), - /* K1 */ be_nested_string("ctypes_bytes_dyn", 915205307, 16), - /* K2 */ be_nested_string("_global_addr", 533766721, 12), - /* K3 */ be_nested_string("_global_def", 646007001, 11), - /* K4 */ be_nested_string("introspect", 164638290, 10), - /* K5 */ be_nested_string("_settings_ptr", 1825772182, 13), - /* K6 */ be_nested_string("get", 1410115415, 3), + ( &(const bvalue[15]) { /* constants */ + /* K0 */ be_nested_str_literal("global"), + /* K1 */ be_nested_str_literal("ctypes_bytes_dyn"), + /* K2 */ be_nested_str_literal("_global_addr"), + /* K3 */ be_nested_str_literal("_global_def"), + /* K4 */ be_nested_str_literal("introspect"), + /* K5 */ be_nested_str_literal("_settings_ptr"), + /* K6 */ be_nested_str_literal("get"), /* K7 */ be_const_int(0), - /* K8 */ be_nested_string("settings", 1745255176, 8), - /* K9 */ be_nested_string("toptr", -915119842, 5), - /* K10 */ be_nested_string("_settings_def", -519406989, 13), - /* K11 */ be_nested_string("wd", 1531424278, 2), - /* K12 */ be_nested_string("", -2128831035, 0), + /* K8 */ be_nested_str_literal("settings"), + /* K9 */ be_nested_str_literal("toptr"), + /* K10 */ be_nested_str_literal("_settings_def"), + /* K11 */ be_nested_str_literal("wd"), + /* K12 */ be_nested_str_literal(""), + /* K13 */ be_nested_str_literal("_debug_present"), + /* K14 */ be_nested_str_literal("debug"), }), (be_nested_const_str("init", 380752755, 4)), ((bstring*) &be_const_str_input), - ( &(const binstruction[24]) { /* code */ + ( &(const binstruction[36]) { /* code */ 0xB8060200, // 0000 GETNGBL R1 K1 0x88080102, // 0001 GETMBR R2 R0 K2 0x880C0103, // 0002 GETMBR R3 R0 K3 @@ -184,7 +186,19 @@ be_local_closure(init, /* name */ 0x7C0C0400, // 0014 CALL R3 2 0x90021003, // 0015 SETMBR R0 K8 R3 0x9002170C, // 0016 SETMBR R0 K11 K12 - 0x80000000, // 0017 RET 0 + 0x500C0000, // 0017 LDBOOL R3 0 0 + 0x90021A03, // 0018 SETMBR R0 K13 R3 + 0xA8020004, // 0019 EXBLK 0 #001F + 0xA40E1C00, // 001A IMPORT R3 K14 + 0x50100200, // 001B LDBOOL R4 1 0 + 0x90021A04, // 001C SETMBR R0 K13 R4 + 0xA8040001, // 001D EXBLK 1 1 + 0x70020003, // 001E JMP #0023 + 0xAC0C0000, // 001F CATCH R3 0 0 + 0x70020000, // 0020 JMP #0022 + 0x70020000, // 0021 JMP #0023 + 0xB0080000, // 0022 RAISE 2 R0 R0 + 0x80000000, // 0023 RET 0 }) ) ); @@ -864,31 +878,31 @@ be_local_closure(load, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[21]) { /* constants */ - /* K0 */ be_nested_string("string", 398550328, 6), - /* K1 */ be_nested_string("path", -2071507658, 4), + /* K0 */ be_nested_str_literal("string"), + /* K1 */ be_nested_str_literal("path"), /* K2 */ be_const_int(0), - /* K3 */ be_nested_string("/", 705468254, 1), - /* K4 */ be_nested_string("split", -2017972765, 5), - /* K5 */ be_nested_string("#", 638357778, 1), + /* K3 */ be_nested_str_literal("/"), + /* K4 */ be_nested_str_literal("split"), + /* K5 */ be_nested_str_literal("#"), /* K6 */ be_const_int(1), - /* K7 */ be_nested_string("find", -1108310694, 4), - /* K8 */ be_nested_string(".", 722245873, 1), - /* K9 */ be_nested_string(".be", 1325797348, 3), - /* K10 */ be_nested_string(".bec", -309694075, 4), - /* K11 */ be_nested_string("io_error", 1970281036, 8), - /* K12 */ be_nested_string("file extension is not '.be' or '.bec'", -1199247657, 37), - /* K13 */ be_nested_string("last_modified", 772177145, 13), - /* K14 */ be_nested_string("c", -435409838, 1), - /* K15 */ be_nested_string("wd", 1531424278, 2), - /* K16 */ be_nested_string("", -2128831035, 0), - /* K17 */ be_nested_string("file", -1427482813, 4), - /* K18 */ be_nested_string("save", -855671224, 4), - /* K19 */ be_nested_string("format", -1180859054, 6), - /* K20 */ be_nested_string("BRY: could not save compiled file %s (%s)", 736659787, 41), + /* K7 */ be_nested_str_literal("find"), + /* K8 */ be_nested_str_literal("."), + /* K9 */ be_nested_str_literal(".be"), + /* K10 */ be_nested_str_literal(".bec"), + /* K11 */ be_nested_str_literal("io_error"), + /* K12 */ be_nested_str_literal("file extension is not '.be' or '.bec'"), + /* K13 */ be_nested_str_literal("last_modified"), + /* K14 */ be_nested_str_literal("c"), + /* K15 */ be_nested_str_literal("wd"), + /* K16 */ be_nested_str_literal(""), + /* K17 */ be_nested_str_literal("file"), + /* K18 */ be_nested_str_literal("save"), + /* K19 */ be_nested_str_literal("format"), + /* K20 */ be_nested_str_literal("BRY: could not save compiled file %s (%s)"), }), (be_nested_const_str("load", -435725847, 4)), ((bstring*) &be_const_str_input), - ( &(const binstruction[108]) { /* code */ + ( &(const binstruction[112]) { /* code */ 0xA40A0000, // 0000 IMPORT R2 K0 0xA40E0200, // 0001 IMPORT R3 K1 0x6010000C, // 0002 GETGBL R4 G12 @@ -931,72 +945,76 @@ be_local_closure(load, /* name */ 0x4024120A, // 0027 CONNECT R9 R9 R10 0x94240C09, // 0028 GETIDX R9 R6 R9 0x1C24130A, // 0029 EQ R9 R9 K10 - 0x74220001, // 002A JMPT R8 #002D - 0x74260000, // 002B JMPT R9 #002D - 0xB006170C, // 002C RAISE 1 K11 K12 - 0x8C28070D, // 002D GETMET R10 R3 K13 - 0x5C300A00, // 002E MOVE R12 R5 - 0x7C280400, // 002F CALL R10 2 - 0x78260005, // 0030 JMPF R9 #0037 - 0x4C2C0000, // 0031 LDNIL R11 - 0x1C2C140B, // 0032 EQ R11 R10 R11 - 0x782E0001, // 0033 JMPF R11 #0036 - 0x502C0000, // 0034 LDBOOL R11 0 0 - 0x80041600, // 0035 RET 1 R11 - 0x70020013, // 0036 JMP #004B - 0x8C2C070D, // 0037 GETMET R11 R3 K13 - 0x0034030E, // 0038 ADD R13 R1 K14 - 0x7C2C0400, // 0039 CALL R11 2 - 0x4C300000, // 003A LDNIL R12 - 0x1C30140C, // 003B EQ R12 R10 R12 - 0x78320004, // 003C JMPF R12 #0042 - 0x4C300000, // 003D LDNIL R12 - 0x1C30160C, // 003E EQ R12 R11 R12 - 0x78320001, // 003F JMPF R12 #0042 - 0x50300000, // 0040 LDBOOL R12 0 0 - 0x80041800, // 0041 RET 1 R12 - 0x4C300000, // 0042 LDNIL R12 - 0x2030160C, // 0043 NE R12 R11 R12 - 0x78320005, // 0044 JMPF R12 #004B - 0x4C300000, // 0045 LDNIL R12 - 0x1C30140C, // 0046 EQ R12 R10 R12 - 0x74320001, // 0047 JMPT R12 #004A - 0x2830160A, // 0048 GE R12 R11 R10 - 0x78320000, // 0049 JMPF R12 #004B - 0x50240200, // 004A LDBOOL R9 1 0 - 0x781E0002, // 004B JMPF R7 #004F - 0x002C0B05, // 004C ADD R11 R5 K5 - 0x90021E0B, // 004D SETMBR R0 K15 R11 - 0x70020000, // 004E JMP #0050 - 0x90021F10, // 004F SETMBR R0 K15 K16 - 0x602C000D, // 0050 GETGBL R11 G13 - 0x5C300200, // 0051 MOVE R12 R1 - 0x58340011, // 0052 LDCONST R13 K17 - 0x7C2C0400, // 0053 CALL R11 2 - 0x74260012, // 0054 JMPT R9 #0068 - 0x741E0011, // 0055 JMPT R7 #0068 - 0xA8020005, // 0056 EXBLK 0 #005D - 0x8C300112, // 0057 GETMET R12 R0 K18 - 0x0038030E, // 0058 ADD R14 R1 K14 - 0x5C3C1600, // 0059 MOVE R15 R11 - 0x7C300600, // 005A CALL R12 3 - 0xA8040001, // 005B EXBLK 1 1 - 0x7002000A, // 005C JMP #0068 - 0xAC300001, // 005D CATCH R12 0 1 - 0x70020007, // 005E JMP #0067 - 0x60340001, // 005F GETGBL R13 G1 - 0x8C380513, // 0060 GETMET R14 R2 K19 - 0x58400014, // 0061 LDCONST R16 K20 - 0x0044030E, // 0062 ADD R17 R1 K14 - 0x5C481800, // 0063 MOVE R18 R12 - 0x7C380800, // 0064 CALL R14 4 - 0x7C340200, // 0065 CALL R13 1 - 0x70020000, // 0066 JMP #0068 - 0xB0080000, // 0067 RAISE 2 R0 R0 - 0x5C301600, // 0068 MOVE R12 R11 - 0x7C300000, // 0069 CALL R12 0 - 0x50300200, // 006A LDBOOL R12 1 0 - 0x80041800, // 006B RET 1 R12 + 0x5C281000, // 002A MOVE R10 R8 + 0x742A0002, // 002B JMPT R10 #002F + 0x5C281200, // 002C MOVE R10 R9 + 0x742A0000, // 002D JMPT R10 #002F + 0xB006170C, // 002E RAISE 1 K11 K12 + 0x8C28070D, // 002F GETMET R10 R3 K13 + 0x5C300A00, // 0030 MOVE R12 R5 + 0x7C280400, // 0031 CALL R10 2 + 0x78260005, // 0032 JMPF R9 #0039 + 0x4C2C0000, // 0033 LDNIL R11 + 0x1C2C140B, // 0034 EQ R11 R10 R11 + 0x782E0001, // 0035 JMPF R11 #0038 + 0x502C0000, // 0036 LDBOOL R11 0 0 + 0x80041600, // 0037 RET 1 R11 + 0x70020013, // 0038 JMP #004D + 0x8C2C070D, // 0039 GETMET R11 R3 K13 + 0x0034030E, // 003A ADD R13 R1 K14 + 0x7C2C0400, // 003B CALL R11 2 + 0x4C300000, // 003C LDNIL R12 + 0x1C30140C, // 003D EQ R12 R10 R12 + 0x78320004, // 003E JMPF R12 #0044 + 0x4C300000, // 003F LDNIL R12 + 0x1C30160C, // 0040 EQ R12 R11 R12 + 0x78320001, // 0041 JMPF R12 #0044 + 0x50300000, // 0042 LDBOOL R12 0 0 + 0x80041800, // 0043 RET 1 R12 + 0x4C300000, // 0044 LDNIL R12 + 0x2030160C, // 0045 NE R12 R11 R12 + 0x78320005, // 0046 JMPF R12 #004D + 0x4C300000, // 0047 LDNIL R12 + 0x1C30140C, // 0048 EQ R12 R10 R12 + 0x74320001, // 0049 JMPT R12 #004C + 0x2830160A, // 004A GE R12 R11 R10 + 0x78320000, // 004B JMPF R12 #004D + 0x50240200, // 004C LDBOOL R9 1 0 + 0x781E0002, // 004D JMPF R7 #0051 + 0x002C0B05, // 004E ADD R11 R5 K5 + 0x90021E0B, // 004F SETMBR R0 K15 R11 + 0x70020000, // 0050 JMP #0052 + 0x90021F10, // 0051 SETMBR R0 K15 K16 + 0x602C000D, // 0052 GETGBL R11 G13 + 0x5C300200, // 0053 MOVE R12 R1 + 0x58340011, // 0054 LDCONST R13 K17 + 0x7C2C0400, // 0055 CALL R11 2 + 0x5C301200, // 0056 MOVE R12 R9 + 0x74320013, // 0057 JMPT R12 #006C + 0x5C300E00, // 0058 MOVE R12 R7 + 0x74320011, // 0059 JMPT R12 #006C + 0xA8020005, // 005A EXBLK 0 #0061 + 0x8C300112, // 005B GETMET R12 R0 K18 + 0x0038030E, // 005C ADD R14 R1 K14 + 0x5C3C1600, // 005D MOVE R15 R11 + 0x7C300600, // 005E CALL R12 3 + 0xA8040001, // 005F EXBLK 1 1 + 0x7002000A, // 0060 JMP #006C + 0xAC300001, // 0061 CATCH R12 0 1 + 0x70020007, // 0062 JMP #006B + 0x60340001, // 0063 GETGBL R13 G1 + 0x8C380513, // 0064 GETMET R14 R2 K19 + 0x58400014, // 0065 LDCONST R16 K20 + 0x0044030E, // 0066 ADD R17 R1 K14 + 0x5C481800, // 0067 MOVE R18 R12 + 0x7C380800, // 0068 CALL R14 4 + 0x7C340200, // 0069 CALL R13 1 + 0x70020000, // 006A JMP #006C + 0xB0080000, // 006B RAISE 2 R0 R0 + 0x5C301600, // 006C MOVE R12 R11 + 0x7C300000, // 006D CALL R12 0 + 0x50300200, // 006E LDBOOL R12 1 0 + 0x80041800, // 006F RET 1 R12 }) ) ); @@ -1982,6 +2000,7 @@ class be_class_tasmota (scope: global, name: Tasmota) { settings, var cmd_res, var wd, var + _debug_present, var _global_def, comptr(&be_tasmota_global_struct) _settings_def, comptr(&be_tasmota_settings_struct) diff --git a/lib/libesp32/Berry/default/embedded/Tasmota.be b/lib/libesp32/Berry/default/embedded/Tasmota.be index abbc22cb6..814af338f 100644 --- a/lib/libesp32/Berry/default/embedded/Tasmota.be +++ b/lib/libesp32/Berry/default/embedded/Tasmota.be @@ -24,10 +24,11 @@ class Tasmota var _cb var wire1 var wire2 - var cmd_res # store the command result, nil if disables, true if capture enabled, contains return value - var global # mapping to TasmotaGlobal + var cmd_res # store the command result, nil if disables, true if capture enabled, contains return value + var global # mapping to TasmotaGlobal var settings - var wd # last working directory + var wd # when load() is called, `tasmota.wd` contains the name of the archive. Ex: `/M5StickC.autoconf#` + var _debug_present # is `import debug` present? def init() # instanciate the mapping object to TasmotaGlobal @@ -38,6 +39,12 @@ class Tasmota self.settings = ctypes_bytes_dyn(introspect.toptr(settings_addr), self._settings_def) end self.wd = "" + self._debug_present = false + try + import debug + self._debug_present = true + except .. + end end # create a specific sub-class for rules: pattern(string) -> closure @@ -416,8 +423,10 @@ class Tasmota if done break end except .. as e,m print(string.format("BRY: Exception> '%s' - %s", e, m)) - import debug - debug.traceback() + if self._debug_present + import debug + debug.traceback() + end end end i += 1 diff --git a/lib/libesp32/Berry/generate/be_const_strtab.h b/lib/libesp32/Berry/generate/be_const_strtab.h index c6a7bf5ec..cee6bc29d 100644 --- a/lib/libesp32/Berry/generate/be_const_strtab.h +++ b/lib/libesp32/Berry/generate/be_const_strtab.h @@ -1,349 +1,350 @@ -extern const bcstring be_const_str_pow; -extern const bcstring be_const_str_remove; -extern const bcstring be_const_str_remove_timer; -extern const bcstring be_const_str_MD5; -extern const bcstring be_const_str__ccmd; -extern const bcstring be_const_str_digital_write; -extern const bcstring be_const_str_dot_p2; -extern const bcstring be_const_str_floor; -extern const bcstring be_const_str_input; -extern const bcstring be_const_str_range; -extern const bcstring be_const_str_atan; -extern const bcstring be_const_str_find_op; -extern const bcstring be_const_str_SERIAL_6N1; -extern const bcstring be_const_str_classname; -extern const bcstring be_const_str_content_start; -extern const bcstring be_const_str_import; -extern const bcstring be_const_str_raise; -extern const bcstring be_const_str_SERIAL_8N2; -extern const bcstring be_const_str_keys; -extern const bcstring be_const_str_content_send_style; -extern const bcstring be_const_str_static; -extern const bcstring be_const_str__begin_transmission; -extern const bcstring be_const_str__request_from; -extern const bcstring be_const_str_isnan; -extern const bcstring be_const_str_reverse_gamma10; -extern const bcstring be_const_str_number; -extern const bcstring be_const_str_resp_cmnd_str; -extern const bcstring be_const_str_run_deferred; -extern const bcstring be_const_str_exec_rules; -extern const bcstring be_const_str_web_send; -extern const bcstring be_const_str_GET; -extern const bcstring be_const_str__rules; -extern const bcstring be_const_str_begin; -extern const bcstring be_const_str_escape; -extern const bcstring be_const_str_I2C_Driver; -extern const bcstring be_const_str_char; -extern const bcstring be_const_str_opt_neq; -extern const bcstring be_const_str_Wire; -extern const bcstring be_const_str_asstring; -extern const bcstring be_const_str_strftime; -extern const bcstring be_const_str_last_modified; -extern const bcstring be_const_str_set; -extern const bcstring be_const_str_add; -extern const bcstring be_const_str_eth; -extern const bcstring be_const_str_publish; -extern const bcstring be_const_str_rtc; -extern const bcstring be_const_str_scan; -extern const bcstring be_const_str_EC_C25519; -extern const bcstring be_const_str_nil; -extern const bcstring be_const_str_ceil; -extern const bcstring be_const_str_item; -extern const bcstring be_const_str_log; -extern const bcstring be_const_str__global_def; -extern const bcstring be_const_str_clear; -extern const bcstring be_const_str_atan2; -extern const bcstring be_const_str_dump; -extern const bcstring be_const_str_fromb64; -extern const bcstring be_const_str_deinit; -extern const bcstring be_const_str_read13; -extern const bcstring be_const_str_SERIAL_8O1; -extern const bcstring be_const_str_SERIAL_6O1; -extern const bcstring be_const_str_add_rule; -extern const bcstring be_const_str_fromstring; -extern const bcstring be_const_str_SERIAL_6E2; -extern const bcstring be_const_str_try_rule; -extern const bcstring be_const_str_gc; -extern const bcstring be_const_str_publish_result; -extern const bcstring be_const_str_response_append; -extern const bcstring be_const_str_continue; -extern const bcstring be_const_str_dot_p1; -extern const bcstring be_const_str__def; -extern const bcstring be_const_str_imin; -extern const bcstring be_const_str_chars_in_string; -extern const bcstring be_const_str_concat; -extern const bcstring be_const_str_content_stop; -extern const bcstring be_const_str_def; -extern const bcstring be_const_str_traceback; -extern const bcstring be_const_str_wire; -extern const bcstring be_const_str_calldepth; -extern const bcstring be_const_str_finish; -extern const bcstring be_const_str_log10; -extern const bcstring be_const_str_name; -extern const bcstring be_const_str_time_str; -extern const bcstring be_const_str_do; -extern const bcstring be_const_str_read; -extern const bcstring be_const_str_set_auth; -extern const bcstring be_const_str_Tasmota; -extern const bcstring be_const_str_SERIAL_7E2; -extern const bcstring be_const_str_resolvecmnd; -extern const bcstring be_const_str___lower__; -extern const bcstring be_const_str_addr; -extern const bcstring be_const_str_gamma8; -extern const bcstring be_const_str_member; -extern const bcstring be_const_str_scale_uint; -extern const bcstring be_const_str_codedump; -extern const bcstring be_const_str_opt_call; -extern const bcstring be_const_str_SERIAL_5N2; -extern const bcstring be_const_str_attrdump; -extern const bcstring be_const_str_hex; -extern const bcstring be_const_str_remove_cmd; -extern const bcstring be_const_str_AudioOutput; -extern const bcstring be_const_str_break; -extern const bcstring be_const_str_SERIAL_5O1; -extern const bcstring be_const_str_rand; -extern const bcstring be_const_str_class; -extern const bcstring be_const_str_public_key; -extern const bcstring be_const_str_search; -extern const bcstring be_const_str_update; -extern const bcstring be_const_str_end; -extern const bcstring be_const_str_i2c_enabled; -extern const bcstring be_const_str_read_bytes; -extern const bcstring be_const_str_fromptr; -extern const bcstring be_const_str_pin_used; -extern const bcstring be_const_str_redirect; -extern const bcstring be_const_str__drivers; -extern const bcstring be_const_str_get_size; -extern const bcstring be_const_str_set_power; -extern const bcstring be_const_str_loop; -extern const bcstring be_const_str_read32; -extern const bcstring be_const_str_add_cmd; -extern const bcstring be_const_str__settings_ptr; -extern const bcstring be_const_str_reset; -extern const bcstring be_const_str__ptr; -extern const bcstring be_const_str_detect; -extern const bcstring be_const_str_reset_search; -extern const bcstring be_const_str_SERIAL_6E1; -extern const bcstring be_const_str__read; -extern const bcstring be_const_str_true; -extern const bcstring be_const_str_opt_eq; -extern const bcstring be_const_str_add_driver; -extern const bcstring be_const_str_tob64; -extern const bcstring be_const_str_wire1; -extern const bcstring be_const_str__timers; -extern const bcstring be_const_str_opt_connect; -extern const bcstring be_const_str_SERIAL_5E1; -extern const bcstring be_const_str_select; -extern const bcstring be_const_str_setbits; -extern const bcstring be_const_str_webclient; -extern const bcstring be_const_str_deg; -extern const bcstring be_const_str_flush; -extern const bcstring be_const_str_hs2rgb; -extern const bcstring be_const_str_SERIAL_8E1; -extern const bcstring be_const_str_setrange; -extern const bcstring be_const_str_dot_len; -extern const bcstring be_const_str_byte; -extern const bcstring be_const_str_issubclass; -extern const bcstring be_const_str_while; -extern const bcstring be_const_str_enabled; -extern const bcstring be_const_str_sin; -extern const bcstring be_const_str_except; -extern const bcstring be_const_str_AudioOutputI2S; -extern const bcstring be_const_str_SERIAL_7N2; -extern const bcstring be_const_str_call; -extern const bcstring be_const_str_imax; -extern const bcstring be_const_str_isrunning; -extern const bcstring be_const_str_read8; -extern const bcstring be_const_str_resp_cmnd_error; -extern const bcstring be_const_str_AudioFileSourceFS; -extern const bcstring be_const_str___iterator__; -extern const bcstring be_const_str_contains; -extern const bcstring be_const_str_web_send_decimal; -extern const bcstring be_const_str_dac_voltage; -extern const bcstring be_const_str_time_reached; -extern const bcstring be_const_str_if; -extern const bcstring be_const_str_read24; -extern const bcstring be_const_str_toptr; -extern const bcstring be_const_str_else; -extern const bcstring be_const_str__global_addr; -extern const bcstring be_const_str_classof; -extern const bcstring be_const_str_SERIAL_7O1; -extern const bcstring be_const_str_print; -extern const bcstring be_const_str_setmember; -extern const bcstring be_const_str_dot_size; -extern const bcstring be_const_str__write; -extern const bcstring be_const_str_init; -extern const bcstring be_const_str_gamma10; -extern const bcstring be_const_str_gen_cb; -extern const bcstring be_const_str_remove_rule; -extern const bcstring be_const_str_ctypes_bytes_dyn; extern const bcstring be_const_str_SERIAL_6N2; -extern const bcstring be_const_str_available; -extern const bcstring be_const_str_cb_dispatch; -extern const bcstring be_const_str_isinstance; -extern const bcstring be_const_str_copy; -extern const bcstring be_const_str_find; -extern const bcstring be_const_str_POST; -extern const bcstring be_const_str_write_bytes; -extern const bcstring be_const_str_; -extern const bcstring be_const_str_type; -extern const bcstring be_const_str_allocated; -extern const bcstring be_const_str_insert; -extern const bcstring be_const_str_tolower; -extern const bcstring be_const_str_dot_w; -extern const bcstring be_const_str_srand; -extern const bcstring be_const_str_wire2; -extern const bcstring be_const_str_format; -extern const bcstring be_const_str_yield; +extern const bcstring be_const_str__begin_transmission; +extern const bcstring be_const_str_set_light; +extern const bcstring be_const_str_time_reached; extern const bcstring be_const_str_SERIAL_5E2; -extern const bcstring be_const_str_reduce; -extern const bcstring be_const_str_resp_cmnd_done; -extern const bcstring be_const_str_abs; -extern const bcstring be_const_str_setitem; -extern const bcstring be_const_str_OneWire; -extern const bcstring be_const_str_upper; -extern const bcstring be_const_str_module; -extern const bcstring be_const_str_counters; +extern const bcstring be_const_str___lower__; +extern const bcstring be_const_str_SERIAL_7O1; +extern const bcstring be_const_str_getbits; +extern const bcstring be_const_str_input; +extern const bcstring be_const_str_dot_size; +extern const bcstring be_const_str_publish_result; +extern const bcstring be_const_str_web_send_decimal; +extern const bcstring be_const_str_def; +extern const bcstring be_const_str__cmd; +extern const bcstring be_const_str_begin; +extern const bcstring be_const_str_resp_cmnd; +extern const bcstring be_const_str_assert; +extern const bcstring be_const_str_set; extern const bcstring be_const_str_tag; -extern const bcstring be_const_str_tanh; -extern const bcstring be_const_str_get_string; -extern const bcstring be_const_str_read12; -extern const bcstring be_const_str_wire_scan; -extern const bcstring be_const_str_seti; -extern const bcstring be_const_str_cmd; -extern const bcstring be_const_str_content_send; -extern const bcstring be_const_str_global; -extern const bcstring be_const_str_var; -extern const bcstring be_const_str_SERIAL_7N1; -extern const bcstring be_const_str_resize; -extern const bcstring be_const_str_split; -extern const bcstring be_const_str_str; -extern const bcstring be_const_str_url_encode; -extern const bcstring be_const_str_get_option; -extern const bcstring be_const_str_listdir; -extern const bcstring be_const_str_tomap; extern const bcstring be_const_str_check_privileged_access; -extern const bcstring be_const_str_pin_mode; -extern const bcstring be_const_str_pin; -extern const bcstring be_const_str_try; -extern const bcstring be_const_str__buffer; -extern const bcstring be_const_str_cos; -extern const bcstring be_const_str_dot_p; -extern const bcstring be_const_str_SERIAL_7O2; -extern const bcstring be_const_str_real; -extern const bcstring be_const_str_set_timer; -extern const bcstring be_const_str_count; -extern const bcstring be_const_str_write; -extern const bcstring be_const_str__settings_def; -extern const bcstring be_const_str_digital_read; -extern const bcstring be_const_str_path; -extern const bcstring be_const_str_delay; -extern const bcstring be_const_str_stop; -extern const bcstring be_const_str_AES_GCM; -extern const bcstring be_const_str_SERIAL_6O2; +extern const bcstring be_const_str_kv; +extern const bcstring be_const_str_publish; +extern const bcstring be_const_str_read32; +extern const bcstring be_const_str_load; +extern const bcstring be_const_str_read13; +extern const bcstring be_const_str_search; +extern const bcstring be_const_str_dac_voltage; +extern const bcstring be_const_str_finish; +extern const bcstring be_const_str_hex; +extern const bcstring be_const_str_isinstance; +extern const bcstring be_const_str_rand; +extern const bcstring be_const_str_POST; +extern const bcstring be_const_str_SERIAL_6E2; +extern const bcstring be_const_str_classname; +extern const bcstring be_const_str__global_def; extern const bcstring be_const_str_open; -extern const bcstring be_const_str_top; -extern const bcstring be_const_str_write_bit; +extern const bcstring be_const_str_redirect; +extern const bcstring be_const_str_AES_GCM; +extern const bcstring be_const_str_resp_cmnd_failed; +extern const bcstring be_const_str_reverse_gamma10; +extern const bcstring be_const_str_strftime; +extern const bcstring be_const_str_insert; +extern const bcstring be_const_str_false; +extern const bcstring be_const_str_arg_size; +extern const bcstring be_const_str_serial; +extern const bcstring be_const_str_OneWire; +extern const bcstring be_const_str_scale_uint; +extern const bcstring be_const_str_return; +extern const bcstring be_const_str_wire; +extern const bcstring be_const_str_write_bytes; +extern const bcstring be_const_str__global_addr; +extern const bcstring be_const_str_exec_tele; +extern const bcstring be_const_str_target_search; +extern const bcstring be_const_str_gamma8; +extern const bcstring be_const_str_pi; extern const bcstring be_const_str_state; -extern const bcstring be_const_str_set_useragent; -extern const bcstring be_const_str_as; -extern const bcstring be_const_str_erase; -extern const bcstring be_const_str_has_arg; -extern const bcstring be_const_str_map; -extern const bcstring be_const_str_on; +extern const bcstring be_const_str_depower; +extern const bcstring be_const_str_init; +extern const bcstring be_const_str_member; +extern const bcstring be_const_str__end_transmission; +extern const bcstring be_const_str_digital_read; +extern const bcstring be_const_str_imin; +extern const bcstring be_const_str_hs2rgb; +extern const bcstring be_const_str_keys; +extern const bcstring be_const_str_real; +extern const bcstring be_const_str_sin; +extern const bcstring be_const_str_SERIAL_7N1; +extern const bcstring be_const_str_ctypes_bytes; +extern const bcstring be_const_str_ctypes_bytes_dyn; +extern const bcstring be_const_str_raise; +extern const bcstring be_const_str_GET; +extern const bcstring be_const_str__settings_def; +extern const bcstring be_const_str_read24; +extern const bcstring be_const_str_cos; +extern const bcstring be_const_str_remove_driver; +extern const bcstring be_const_str__settings_ptr; +extern const bcstring be_const_str_memory; +extern const bcstring be_const_str_set_auth; +extern const bcstring be_const_str_content_send_style; +extern const bcstring be_const_str_class; +extern const bcstring be_const_str_SERIAL_7E2; +extern const bcstring be_const_str_shared_key; +extern const bcstring be_const_str_tanh; +extern const bcstring be_const_str_nil; +extern const bcstring be_const_str_get_power; +extern const bcstring be_const_str_last_modified; +extern const bcstring be_const_str_resolvecmnd; +extern const bcstring be_const_str__read; +extern const bcstring be_const_str_atan; +extern const bcstring be_const_str_content_button; +extern const bcstring be_const_str_setbits; +extern const bcstring be_const_str_upper; +extern const bcstring be_const_str_contains; +extern const bcstring be_const_str_time_str; +extern const bcstring be_const_str_arch; +extern const bcstring be_const_str_fromptr; +extern const bcstring be_const_str_push; +extern const bcstring be_const_str_srand; +extern const bcstring be_const_str_geti; +extern const bcstring be_const_str_seti; +extern const bcstring be_const_str_add_cmd; +extern const bcstring be_const_str_cmd; +extern const bcstring be_const_str_get_switch; +extern const bcstring be_const_str_size; +extern const bcstring be_const_str_try; +extern const bcstring be_const_str_web_send; +extern const bcstring be_const_str_except; +extern const bcstring be_const_str_SERIAL_5O1; +extern const bcstring be_const_str_SERIAL_8E2; +extern const bcstring be_const_str__available; +extern const bcstring be_const_str_codedump; +extern const bcstring be_const_str_wire2; +extern const bcstring be_const_str_dump; +extern const bcstring be_const_str_exec_cmd; +extern const bcstring be_const_str_add; +extern const bcstring be_const_str_exp; +extern const bcstring be_const_str_isrunning; +extern const bcstring be_const_str_remove_rule; +extern const bcstring be_const_str_run_deferred; +extern const bcstring be_const_str_scan; +extern const bcstring be_const_str_for; +extern const bcstring be_const_str_set_timer; +extern const bcstring be_const_str_url_encode; +extern const bcstring be_const_str_addr; +extern const bcstring be_const_str___upper__; +extern const bcstring be_const_str_loop; extern const bcstring be_const_str_AudioGeneratorWAV; +extern const bcstring be_const_str_chars_in_string; +extern const bcstring be_const_str_cosh; +extern const bcstring be_const_str_import; +extern const bcstring be_const_str_SERIAL_5N2; +extern const bcstring be_const_str_type; +extern const bcstring be_const_str_clear; +extern const bcstring be_const_str_SERIAL_8N1; +extern const bcstring be_const_str_issubclass; +extern const bcstring be_const_str_remove_timer; +extern const bcstring be_const_str_sinh; +extern const bcstring be_const_str_AudioGeneratorMP3; +extern const bcstring be_const_str_Wire; +extern const bcstring be_const_str_get_light; +extern const bcstring be_const_str_get_option; +extern const bcstring be_const_str_list; +extern const bcstring be_const_str_stop; +extern const bcstring be_const_str_try_rule; +extern const bcstring be_const_str_webclient; +extern const bcstring be_const_str_dot_p2; +extern const bcstring be_const_str_has; +extern const bcstring be_const_str__request_from; +extern const bcstring be_const_str_setrange; +extern const bcstring be_const_str_I2C_Driver; +extern const bcstring be_const_str_ceil; +extern const bcstring be_const_str_else; +extern const bcstring be_const_str_concat; +extern const bcstring be_const_str_set_power; +extern const bcstring be_const_str_tomap; +extern const bcstring be_const_str_resp_cmnd_error; +extern const bcstring be_const_str_add_header; +extern const bcstring be_const_str_eth; +extern const bcstring be_const_str_write_bit; +extern const bcstring be_const_str_exists; +extern const bcstring be_const_str_pow; +extern const bcstring be_const_str_select; +extern const bcstring be_const_str_allocated; +extern const bcstring be_const_str_classof; +extern const bcstring be_const_str_if; +extern const bcstring be_const_str_SERIAL_5E1; +extern const bcstring be_const_str_arg; +extern const bcstring be_const_str_cb_dispatch; +extern const bcstring be_const_str_response_append; +extern const bcstring be_const_str_pin_used; +extern const bcstring be_const_str_write; +extern const bcstring be_const_str_write8; +extern const bcstring be_const_str_SERIAL_6O2; +extern const bcstring be_const_str_log; +extern const bcstring be_const_str_pin_mode; +extern const bcstring be_const_str_read12; +extern const bcstring be_const_str_resp_cmnd_str; +extern const bcstring be_const_str_abs; +extern const bcstring be_const_str_digital_write; +extern const bcstring be_const_str_static; +extern const bcstring be_const_str_bytes; +extern const bcstring be_const_str_find_op; +extern const bcstring be_const_str_call; +extern const bcstring be_const_str_cmd_res; +extern const bcstring be_const_str_opt_eq; +extern const bcstring be_const_str_save; +extern const bcstring be_const_str_find_key_i; extern const bcstring be_const_str__cb; -extern const bcstring be_const_str_decrypt; +extern const bcstring be_const_str_Tasmota; +extern const bcstring be_const_str_public_key; +extern const bcstring be_const_str_as; +extern const bcstring be_const_str_dot_w; +extern const bcstring be_const_str_SERIAL_8O1; +extern const bcstring be_const_str_compile; +extern const bcstring be_const_str_range; +extern const bcstring be_const_str_add_rule; +extern const bcstring be_const_str__ptr; +extern const bcstring be_const_str_delay; +extern const bcstring be_const_str_pop; +extern const bcstring be_const_str_reset; +extern const bcstring be_const_str_wire_scan; +extern const bcstring be_const_str_reset_search; +extern const bcstring be_const_str_tolower; +extern const bcstring be_const_str_SERIAL_7O2; +extern const bcstring be_const_str_asin; +extern const bcstring be_const_str_nan; +extern const bcstring be_const_str_deg; +extern const bcstring be_const_str_log10; +extern const bcstring be_const_str_char; +extern const bcstring be_const_str_get_size; +extern const bcstring be_const_str_opt_call; +extern const bcstring be_const_str_end; +extern const bcstring be_const_str_SERIAL_7N2; +extern const bcstring be_const_str_time_dump; +extern const bcstring be_const_str_listdir; +extern const bcstring be_const_str_wifi; +extern const bcstring be_const_str_read_bytes; +extern const bcstring be_const_str_reverse; +extern const bcstring be_const_str_SERIAL_6E1; +extern const bcstring be_const_str_SERIAL_5O2; +extern const bcstring be_const_str_SERIAL_8E1; +extern const bcstring be_const_str_asstring; +extern const bcstring be_const_str_deinit; +extern const bcstring be_const_str_encrypt; +extern const bcstring be_const_str_iter; +extern const bcstring be_const_str_millis; +extern const bcstring be_const_str_AudioOutput; +extern const bcstring be_const_str_members; +extern const bcstring be_const_str_rtc; +extern const bcstring be_const_str_SERIAL_6N1; +extern const bcstring be_const_str__write; +extern const bcstring be_const_str_content_start; +extern const bcstring be_const_str_module; +extern const bcstring be_const_str_item; +extern const bcstring be_const_str_remove_cmd; +extern const bcstring be_const_str_MD5; extern const bcstring be_const_str_sqrt; extern const bcstring be_const_str_SERIAL_5N1; -extern const bcstring be_const_str_find_key_i; -extern const bcstring be_const_str_arg; -extern const bcstring be_const_str_depower; -extern const bcstring be_const_str_write_file; -extern const bcstring be_const_str_SERIAL_5O2; -extern const bcstring be_const_str_get_light; -extern const bcstring be_const_str_pop; -extern const bcstring be_const_str_exec_tele; -extern const bcstring be_const_str_set_light; -extern const bcstring be_const_str_set_timeouts; -extern const bcstring be_const_str_sinh; -extern const bcstring be_const_str_AudioGenerator; -extern const bcstring be_const_str_SERIAL_7E1; -extern const bcstring be_const_str_getbits; -extern const bcstring be_const_str_shared_key; -extern const bcstring be_const_str_time_dump; -extern const bcstring be_const_str_content_button; -extern const bcstring be_const_str_geti; -extern const bcstring be_const_str_arch; -extern const bcstring be_const_str_asin; -extern const bcstring be_const_str_get_free_heap; -extern const bcstring be_const_str_resp_cmnd; -extern const bcstring be_const_str_content_flush; -extern const bcstring be_const_str_millis; -extern const bcstring be_const_str_serial; -extern const bcstring be_const_str_skip; -extern const bcstring be_const_str_event; -extern const bcstring be_const_str_opt_add; -extern const bcstring be_const_str_bus; -extern const bcstring be_const_str_acos; -extern const bcstring be_const_str_bytes; -extern const bcstring be_const_str_compile; -extern const bcstring be_const_str_get; -extern const bcstring be_const_str_tan; -extern const bcstring be_const_str_encrypt; -extern const bcstring be_const_str_cmd_res; -extern const bcstring be_const_str_collect; -extern const bcstring be_const_str_arg_size; -extern const bcstring be_const_str_reverse; -extern const bcstring be_const_str_close; -extern const bcstring be_const_str_members; -extern const bcstring be_const_str_assert; -extern const bcstring be_const_str_exec_cmd; -extern const bcstring be_const_str_get_power; -extern const bcstring be_const_str_resp_cmnd_failed; -extern const bcstring be_const_str_target_search; -extern const bcstring be_const_str_AudioFileSource; -extern const bcstring be_const_str_SERIAL_8N1; -extern const bcstring be_const_str_pi; -extern const bcstring be_const_str_add_header; -extern const bcstring be_const_str_list; -extern const bcstring be_const_str_read_sensors; -extern const bcstring be_const_str_super; -extern const bcstring be_const_str_has; -extern const bcstring be_const_str___upper__; -extern const bcstring be_const_str_exp; -extern const bcstring be_const_str_int; -extern const bcstring be_const_str_size; -extern const bcstring be_const_str_for; -extern const bcstring be_const_str_ctypes_bytes; -extern const bcstring be_const_str_wifi; -extern const bcstring be_const_str_elif; -extern const bcstring be_const_str_arg_name; -extern const bcstring be_const_str_cosh; -extern const bcstring be_const_str_lower; -extern const bcstring be_const_str_push; -extern const bcstring be_const_str_save; -extern const bcstring be_const_str_load; -extern const bcstring be_const_str_SERIAL_8E2; -extern const bcstring be_const_str_nan; -extern const bcstring be_const_str_remove_driver; -extern const bcstring be_const_str_write8; -extern const bcstring be_const_str__get_cb; -extern const bcstring be_const_str_iter; -extern const bcstring be_const_str__cmd; -extern const bcstring be_const_str_exists; -extern const bcstring be_const_str_AudioGeneratorMP3; -extern const bcstring be_const_str__end_transmission; -extern const bcstring be_const_str_get_switch; -extern const bcstring be_const_str__available; -extern const bcstring be_const_str_false; -extern const bcstring be_const_str_settings; -extern const bcstring be_const_str_wd; -extern const bcstring be_const_str_SERIAL_8O2; -extern const bcstring be_const_str_rad; -extern const bcstring be_const_str_kv; -extern const bcstring be_const_str_toupper; -extern const bcstring be_const_str_tr; -extern const bcstring be_const_str_return; -extern const bcstring be_const_str_memory; +extern const bcstring be_const_str_break; +extern const bcstring be_const_str_map; +extern const bcstring be_const_str_setmember; extern const bcstring be_const_str_tostring; +extern const bcstring be_const_str_AudioGenerator; +extern const bcstring be_const_str_while; +extern const bcstring be_const_str_event; +extern const bcstring be_const_str_resp_cmnd_done; +extern const bcstring be_const_str_AudioOutputI2S; +extern const bcstring be_const_str_has_arg; +extern const bcstring be_const_str_floor; +extern const bcstring be_const_str_read; +extern const bcstring be_const_str_remove; +extern const bcstring be_const_str_calldepth; +extern const bcstring be_const_str_lower; +extern const bcstring be_const_str_path; +extern const bcstring be_const_str_gamma10; +extern const bcstring be_const_str_get; +extern const bcstring be_const_str_elif; +extern const bcstring be_const_str__buffer; +extern const bcstring be_const_str_exec_rules; +extern const bcstring be_const_str_pin; +extern const bcstring be_const_str_collect; +extern const bcstring be_const_str_enabled; +extern const bcstring be_const_str_global; +extern const bcstring be_const_str_acos; +extern const bcstring be_const_str_content_stop; +extern const bcstring be_const_str_read8; +extern const bcstring be_const_str_wire1; +extern const bcstring be_const_str_fromstring; +extern const bcstring be_const_str_setitem; +extern const bcstring be_const_str__debug_present; +extern const bcstring be_const_str_erase; +extern const bcstring be_const_str_i2c_enabled; +extern const bcstring be_const_str_resize; +extern const bcstring be_const_str_decrypt; +extern const bcstring be_const_str_escape; +extern const bcstring be_const_str_isnan; +extern const bcstring be_const_str_skip; +extern const bcstring be_const_str_var; +extern const bcstring be_const_str_dot_p; +extern const bcstring be_const_str_write_file; +extern const bcstring be_const_str_copy; +extern const bcstring be_const_str_str; +extern const bcstring be_const_str_super; +extern const bcstring be_const_str_update; +extern const bcstring be_const_str__def; +extern const bcstring be_const_str__drivers; +extern const bcstring be_const_str_imax; +extern const bcstring be_const_str_add_driver; +extern const bcstring be_const_str_dot_len; +extern const bcstring be_const_str_SERIAL_6O1; +extern const bcstring be_const_str_attrdump; +extern const bcstring be_const_str_on; +extern const bcstring be_const_str_rad; +extern const bcstring be_const_str_bus; +extern const bcstring be_const_str_yield; +extern const bcstring be_const_str_top; +extern const bcstring be_const_str_get_string; +extern const bcstring be_const_str_read_sensors; +extern const bcstring be_const_str_settings; +extern const bcstring be_const_str__get_cb; +extern const bcstring be_const_str_int; +extern const bcstring be_const_str_opt_neq; +extern const bcstring be_const_str_gen_cb; +extern const bcstring be_const_str__timers; +extern const bcstring be_const_str_continue; +extern const bcstring be_const_str_SERIAL_7E1; +extern const bcstring be_const_str_AudioFileSource; +extern const bcstring be_const_str_format; +extern const bcstring be_const_str_EC_C25519; +extern const bcstring be_const_str_close; +extern const bcstring be_const_str_content_flush; +extern const bcstring be_const_str_reduce; +extern const bcstring be_const_str_tr; +extern const bcstring be_const_str_available; +extern const bcstring be_const_str_traceback; +extern const bcstring be_const_str_opt_add; +extern const bcstring be_const_str_SERIAL_8N2; +extern const bcstring be_const_str_wd; +extern const bcstring be_const_str___iterator__; +extern const bcstring be_const_str_fromb64; +extern const bcstring be_const_str_number; +extern const bcstring be_const_str_print; +extern const bcstring be_const_str_set_useragent; +extern const bcstring be_const_str_tan; +extern const bcstring be_const_str_do; +extern const bcstring be_const_str_; +extern const bcstring be_const_str_opt_connect; +extern const bcstring be_const_str__rules; +extern const bcstring be_const_str_dot_p1; +extern const bcstring be_const_str_find; +extern const bcstring be_const_str_name; +extern const bcstring be_const_str_toptr; +extern const bcstring be_const_str_arg_name; +extern const bcstring be_const_str_byte; +extern const bcstring be_const_str_gc; +extern const bcstring be_const_str_count; +extern const bcstring be_const_str_counters; +extern const bcstring be_const_str_tob64; +extern const bcstring be_const_str_AudioFileSourceFS; +extern const bcstring be_const_str_get_free_heap; +extern const bcstring be_const_str_atan2; +extern const bcstring be_const_str_set_timeouts; +extern const bcstring be_const_str_toupper; +extern const bcstring be_const_str__ccmd; +extern const bcstring be_const_str_content_send; +extern const bcstring be_const_str_flush; +extern const bcstring be_const_str_true; +extern const bcstring be_const_str_detect; +extern const bcstring be_const_str_SERIAL_8O2; +extern const bcstring be_const_str_split; diff --git a/lib/libesp32/Berry/generate/be_const_strtab_def.h b/lib/libesp32/Berry/generate/be_const_strtab_def.h index e7e4bc0f2..16488ae94 100644 --- a/lib/libesp32/Berry/generate/be_const_strtab_def.h +++ b/lib/libesp32/Berry/generate/be_const_strtab_def.h @@ -1,521 +1,523 @@ -be_define_const_str(pow, "pow", 1479764693u, 0, 3, &be_const_str_remove); -be_define_const_str(remove, "remove", 3683784189u, 0, 6, &be_const_str_remove_timer); -be_define_const_str(remove_timer, "remove_timer", 4141472215u, 0, 12, NULL); -be_define_const_str(MD5, "MD5", 1935726387u, 0, 3, &be_const_str__ccmd); -be_define_const_str(_ccmd, "_ccmd", 2163421413u, 0, 5, &be_const_str_digital_write); -be_define_const_str(digital_write, "digital_write", 3435877979u, 0, 13, NULL); -be_define_const_str(dot_p2, ".p2", 232398067u, 0, 3, &be_const_str_floor); -be_define_const_str(floor, "floor", 3102149661u, 0, 5, &be_const_str_input); -be_define_const_str(input, "input", 4191711099u, 0, 5, &be_const_str_range); -be_define_const_str(range, "range", 4208725202u, 0, 5, NULL); -be_define_const_str(atan, "atan", 108579519u, 0, 4, &be_const_str_find_op); -be_define_const_str(find_op, "find_op", 3766713376u, 0, 7, NULL); -be_define_const_str(SERIAL_6N1, "SERIAL_6N1", 198895701u, 0, 10, &be_const_str_classname); -be_define_const_str(classname, "classname", 1998589948u, 0, 9, NULL); -be_define_const_str(content_start, "content_start", 2937509069u, 0, 13, &be_const_str_import); -be_define_const_str(import, "import", 288002260u, 66, 6, &be_const_str_raise); -be_define_const_str(raise, "raise", 1593437475u, 70, 5, NULL); -be_define_const_str(SERIAL_8N2, "SERIAL_8N2", 2386074854u, 0, 10, &be_const_str_keys); -be_define_const_str(keys, "keys", 4182378701u, 0, 4, NULL); -be_define_const_str(content_send_style, "content_send_style", 1087907647u, 0, 18, &be_const_str_static); -be_define_const_str(static, "static", 3532702267u, 71, 6, NULL); -be_define_const_str(_begin_transmission, "_begin_transmission", 2779461176u, 0, 19, &be_const_str__request_from); -be_define_const_str(_request_from, "_request_from", 3965148604u, 0, 13, &be_const_str_isnan); -be_define_const_str(isnan, "isnan", 2981347434u, 0, 5, &be_const_str_reverse_gamma10); -be_define_const_str(reverse_gamma10, "reverse_gamma10", 739112262u, 0, 15, NULL); -be_define_const_str(number, "number", 467038368u, 0, 6, &be_const_str_resp_cmnd_str); -be_define_const_str(resp_cmnd_str, "resp_cmnd_str", 737845590u, 0, 13, &be_const_str_run_deferred); -be_define_const_str(run_deferred, "run_deferred", 371594696u, 0, 12, NULL); -be_define_const_str(exec_rules, "exec_rules", 1445221092u, 0, 10, &be_const_str_web_send); -be_define_const_str(web_send, "web_send", 2989941448u, 0, 8, NULL); -be_define_const_str(GET, "GET", 2531704439u, 0, 3, &be_const_str__rules); -be_define_const_str(_rules, "_rules", 4266217105u, 0, 6, &be_const_str_begin); -be_define_const_str(begin, "begin", 1748273790u, 0, 5, &be_const_str_escape); -be_define_const_str(escape, "escape", 2652972038u, 0, 6, NULL); -be_define_const_str(I2C_Driver, "I2C_Driver", 1714501658u, 0, 10, &be_const_str_char); -be_define_const_str(char, "char", 2823553821u, 0, 4, NULL); -be_define_const_str(opt_neq, "!=", 2428715011u, 0, 2, &be_const_str_Wire); -be_define_const_str(Wire, "Wire", 1938276536u, 0, 4, &be_const_str_asstring); -be_define_const_str(asstring, "asstring", 1298225088u, 0, 8, &be_const_str_strftime); -be_define_const_str(strftime, "strftime", 187738851u, 0, 8, NULL); -be_define_const_str(last_modified, "last_modified", 772177145u, 0, 13, &be_const_str_set); -be_define_const_str(set, "set", 3324446467u, 0, 3, NULL); -be_define_const_str(add, "add", 993596020u, 0, 3, &be_const_str_eth); -be_define_const_str(eth, "eth", 2191266556u, 0, 3, &be_const_str_publish); -be_define_const_str(publish, "publish", 264247304u, 0, 7, NULL); -be_define_const_str(rtc, "rtc", 1070575216u, 0, 3, &be_const_str_scan); -be_define_const_str(scan, "scan", 3974641896u, 0, 4, NULL); -be_define_const_str(EC_C25519, "EC_C25519", 95492591u, 0, 9, &be_const_str_nil); -be_define_const_str(nil, "nil", 228849900u, 63, 3, NULL); -be_define_const_str(ceil, "ceil", 1659167240u, 0, 4, &be_const_str_item); -be_define_const_str(item, "item", 2671260646u, 0, 4, NULL); -be_define_const_str(log, "log", 1062293841u, 0, 3, NULL); -be_define_const_str(_global_def, "_global_def", 646007001u, 0, 11, &be_const_str_clear); -be_define_const_str(clear, "clear", 1550717474u, 0, 5, NULL); -be_define_const_str(atan2, "atan2", 3173440503u, 0, 5, &be_const_str_dump); -be_define_const_str(dump, "dump", 3663001223u, 0, 4, &be_const_str_fromb64); -be_define_const_str(fromb64, "fromb64", 2717019639u, 0, 7, NULL); -be_define_const_str(deinit, "deinit", 2345559592u, 0, 6, &be_const_str_read13); -be_define_const_str(read13, "read13", 12887293u, 0, 6, NULL); -be_define_const_str(SERIAL_8O1, "SERIAL_8O1", 289122742u, 0, 10, NULL); -be_define_const_str(SERIAL_6O1, "SERIAL_6O1", 266153272u, 0, 10, &be_const_str_add_rule); -be_define_const_str(add_rule, "add_rule", 596540743u, 0, 8, &be_const_str_fromstring); -be_define_const_str(fromstring, "fromstring", 610302344u, 0, 10, NULL); -be_define_const_str(SERIAL_6E2, "SERIAL_6E2", 317471867u, 0, 10, &be_const_str_try_rule); -be_define_const_str(try_rule, "try_rule", 1986449405u, 0, 8, NULL); -be_define_const_str(gc, "gc", 1042313471u, 0, 2, &be_const_str_publish_result); -be_define_const_str(publish_result, "publish_result", 2013351252u, 0, 14, &be_const_str_response_append); -be_define_const_str(response_append, "response_append", 450346371u, 0, 15, NULL); -be_define_const_str(continue, "continue", 2977070660u, 59, 8, NULL); -be_define_const_str(dot_p1, ".p1", 249175686u, 0, 3, &be_const_str__def); -be_define_const_str(_def, "_def", 1985022181u, 0, 4, &be_const_str_imin); -be_define_const_str(imin, "imin", 2714127864u, 0, 4, NULL); -be_define_const_str(chars_in_string, "chars_in_string", 3148785132u, 0, 15, &be_const_str_concat); -be_define_const_str(concat, "concat", 4124019837u, 0, 6, &be_const_str_content_stop); -be_define_const_str(content_stop, "content_stop", 658554751u, 0, 12, &be_const_str_def); +be_define_const_str(SERIAL_6N2, "SERIAL_6N2", 148562844u, 0, 10, &be_const_str__begin_transmission); +be_define_const_str(_begin_transmission, "_begin_transmission", 2779461176u, 0, 19, &be_const_str_set_light); +be_define_const_str(set_light, "set_light", 3176076152u, 0, 9, NULL); +be_define_const_str(time_reached, "time_reached", 2075136773u, 0, 12, NULL); +be_define_const_str(SERIAL_5E2, "SERIAL_5E2", 1180552854u, 0, 10, &be_const_str___lower__); +be_define_const_str(__lower__, "__lower__", 123855590u, 0, 9, NULL); +be_define_const_str(SERIAL_7O1, "SERIAL_7O1", 1823802675u, 0, 10, &be_const_str_getbits); +be_define_const_str(getbits, "getbits", 3094168979u, 0, 7, &be_const_str_input); +be_define_const_str(input, "input", 4191711099u, 0, 5, NULL); +be_define_const_str(dot_size, ".size", 1965188224u, 0, 5, &be_const_str_publish_result); +be_define_const_str(publish_result, "publish_result", 2013351252u, 0, 14, &be_const_str_web_send_decimal); +be_define_const_str(web_send_decimal, "web_send_decimal", 1407210204u, 0, 16, &be_const_str_def); be_define_const_str(def, "def", 3310976652u, 55, 3, NULL); -be_define_const_str(traceback, "traceback", 3385188109u, 0, 9, &be_const_str_wire); -be_define_const_str(wire, "wire", 4082753944u, 0, 4, NULL); -be_define_const_str(calldepth, "calldepth", 3122364302u, 0, 9, NULL); -be_define_const_str(finish, "finish", 1494643858u, 0, 6, &be_const_str_log10); -be_define_const_str(log10, "log10", 2346846000u, 0, 5, &be_const_str_name); -be_define_const_str(name, "name", 2369371622u, 0, 4, &be_const_str_time_str); -be_define_const_str(time_str, "time_str", 2613827612u, 0, 8, &be_const_str_do); -be_define_const_str(do, "do", 1646057492u, 65, 2, NULL); -be_define_const_str(read, "read", 3470762949u, 0, 4, &be_const_str_set_auth); -be_define_const_str(set_auth, "set_auth", 1057170930u, 0, 8, NULL); -be_define_const_str(Tasmota, "Tasmota", 4047617668u, 0, 7, NULL); -be_define_const_str(SERIAL_7E2, "SERIAL_7E2", 97385204u, 0, 10, &be_const_str_resolvecmnd); -be_define_const_str(resolvecmnd, "resolvecmnd", 993361485u, 0, 11, NULL); -be_define_const_str(__lower__, "__lower__", 123855590u, 0, 9, &be_const_str_addr); -be_define_const_str(addr, "addr", 1087856498u, 0, 4, &be_const_str_gamma8); -be_define_const_str(gamma8, "gamma8", 3802843830u, 0, 6, NULL); -be_define_const_str(member, "member", 719708611u, 0, 6, &be_const_str_scale_uint); -be_define_const_str(scale_uint, "scale_uint", 3090811094u, 0, 10, NULL); -be_define_const_str(codedump, "codedump", 1786337906u, 0, 8, NULL); -be_define_const_str(opt_call, "()", 685372826u, 0, 2, &be_const_str_SERIAL_5N2); -be_define_const_str(SERIAL_5N2, "SERIAL_5N2", 3363364537u, 0, 10, NULL); -be_define_const_str(attrdump, "attrdump", 1521571304u, 0, 8, &be_const_str_hex); -be_define_const_str(hex, "hex", 4273249610u, 0, 3, &be_const_str_remove_cmd); -be_define_const_str(remove_cmd, "remove_cmd", 3832315702u, 0, 10, NULL); -be_define_const_str(AudioOutput, "AudioOutput", 3257792048u, 0, 11, &be_const_str_break); -be_define_const_str(break, "break", 3378807160u, 58, 5, NULL); -be_define_const_str(SERIAL_5O1, "SERIAL_5O1", 3782657917u, 0, 10, &be_const_str_rand); -be_define_const_str(rand, "rand", 2711325910u, 0, 4, &be_const_str_class); -be_define_const_str(class, "class", 2872970239u, 57, 5, NULL); -be_define_const_str(public_key, "public_key", 4169142980u, 0, 10, &be_const_str_search); -be_define_const_str(search, "search", 2150836393u, 0, 6, &be_const_str_update); -be_define_const_str(update, "update", 672109684u, 0, 6, &be_const_str_end); -be_define_const_str(end, "end", 1787721130u, 56, 3, NULL); -be_define_const_str(i2c_enabled, "i2c_enabled", 218388101u, 0, 11, &be_const_str_read_bytes); -be_define_const_str(read_bytes, "read_bytes", 3576733173u, 0, 10, NULL); -be_define_const_str(fromptr, "fromptr", 666189689u, 0, 7, &be_const_str_pin_used); -be_define_const_str(pin_used, "pin_used", 4033854612u, 0, 8, &be_const_str_redirect); -be_define_const_str(redirect, "redirect", 389758641u, 0, 8, NULL); -be_define_const_str(_drivers, "_drivers", 3260328985u, 0, 8, &be_const_str_get_size); -be_define_const_str(get_size, "get_size", 2803644713u, 0, 8, &be_const_str_set_power); -be_define_const_str(set_power, "set_power", 549820893u, 0, 9, NULL); -be_define_const_str(loop, "loop", 3723446379u, 0, 4, &be_const_str_read32); -be_define_const_str(read32, "read32", 1741276240u, 0, 6, NULL); -be_define_const_str(add_cmd, "add_cmd", 3361630879u, 0, 7, NULL); -be_define_const_str(_settings_ptr, "_settings_ptr", 1825772182u, 0, 13, &be_const_str_reset); -be_define_const_str(reset, "reset", 1695364032u, 0, 5, NULL); -be_define_const_str(_ptr, "_ptr", 306235816u, 0, 4, &be_const_str_detect); -be_define_const_str(detect, "detect", 8884370u, 0, 6, &be_const_str_reset_search); -be_define_const_str(reset_search, "reset_search", 1350414305u, 0, 12, NULL); -be_define_const_str(SERIAL_6E1, "SERIAL_6E1", 334249486u, 0, 10, &be_const_str__read); -be_define_const_str(_read, "_read", 346717030u, 0, 5, NULL); -be_define_const_str(true, "true", 1303515621u, 61, 4, NULL); -be_define_const_str(opt_eq, "==", 2431966415u, 0, 2, &be_const_str_add_driver); -be_define_const_str(add_driver, "add_driver", 1654458371u, 0, 10, &be_const_str_tob64); -be_define_const_str(tob64, "tob64", 373777640u, 0, 5, &be_const_str_wire1); -be_define_const_str(wire1, "wire1", 3212721419u, 0, 5, NULL); -be_define_const_str(_timers, "_timers", 2600100916u, 0, 7, NULL); -be_define_const_str(opt_connect, "..", 2748622605u, 0, 2, &be_const_str_SERIAL_5E1); -be_define_const_str(SERIAL_5E1, "SERIAL_5E1", 1163775235u, 0, 10, &be_const_str_select); -be_define_const_str(select, "select", 297952813u, 0, 6, &be_const_str_setbits); -be_define_const_str(setbits, "setbits", 2762408167u, 0, 7, &be_const_str_webclient); -be_define_const_str(webclient, "webclient", 4076389146u, 0, 9, NULL); -be_define_const_str(deg, "deg", 3327754271u, 0, 3, &be_const_str_flush); -be_define_const_str(flush, "flush", 3002334877u, 0, 5, &be_const_str_hs2rgb); -be_define_const_str(hs2rgb, "hs2rgb", 1040816349u, 0, 6, NULL); -be_define_const_str(SERIAL_8E1, "SERIAL_8E1", 2371121616u, 0, 10, &be_const_str_setrange); -be_define_const_str(setrange, "setrange", 3794019032u, 0, 8, NULL); -be_define_const_str(dot_len, ".len", 850842136u, 0, 4, &be_const_str_byte); -be_define_const_str(byte, "byte", 1683620383u, 0, 4, &be_const_str_issubclass); -be_define_const_str(issubclass, "issubclass", 4078395519u, 0, 10, &be_const_str_while); -be_define_const_str(while, "while", 231090382u, 53, 5, NULL); -be_define_const_str(enabled, "enabled", 49525662u, 0, 7, &be_const_str_sin); -be_define_const_str(sin, "sin", 3761252941u, 0, 3, &be_const_str_except); -be_define_const_str(except, "except", 950914032u, 69, 6, NULL); -be_define_const_str(AudioOutputI2S, "AudioOutputI2S", 638031784u, 0, 14, &be_const_str_SERIAL_7N2); -be_define_const_str(SERIAL_7N2, "SERIAL_7N2", 1874282627u, 0, 10, &be_const_str_call); -be_define_const_str(call, "call", 3018949801u, 0, 4, &be_const_str_imax); -be_define_const_str(imax, "imax", 3084515410u, 0, 4, NULL); -be_define_const_str(isrunning, "isrunning", 1688182268u, 0, 9, &be_const_str_read8); -be_define_const_str(read8, "read8", 2802788167u, 0, 5, &be_const_str_resp_cmnd_error); -be_define_const_str(resp_cmnd_error, "resp_cmnd_error", 2404088863u, 0, 15, NULL); -be_define_const_str(AudioFileSourceFS, "AudioFileSourceFS", 1839147653u, 0, 17, &be_const_str___iterator__); -be_define_const_str(__iterator__, "__iterator__", 3884039703u, 0, 12, &be_const_str_contains); -be_define_const_str(contains, "contains", 1825239352u, 0, 8, &be_const_str_web_send_decimal); -be_define_const_str(web_send_decimal, "web_send_decimal", 1407210204u, 0, 16, NULL); -be_define_const_str(dac_voltage, "dac_voltage", 1552257222u, 0, 11, NULL); -be_define_const_str(time_reached, "time_reached", 2075136773u, 0, 12, &be_const_str_if); -be_define_const_str(if, "if", 959999494u, 50, 2, NULL); -be_define_const_str(read24, "read24", 1808533811u, 0, 6, &be_const_str_toptr); -be_define_const_str(toptr, "toptr", 3379847454u, 0, 5, &be_const_str_else); -be_define_const_str(else, "else", 3183434736u, 52, 4, NULL); -be_define_const_str(_global_addr, "_global_addr", 533766721u, 0, 12, &be_const_str_classof); -be_define_const_str(classof, "classof", 1796577762u, 0, 7, NULL); -be_define_const_str(SERIAL_7O1, "SERIAL_7O1", 1823802675u, 0, 10, &be_const_str_print); -be_define_const_str(print, "print", 372738696u, 0, 5, &be_const_str_setmember); -be_define_const_str(setmember, "setmember", 1432909441u, 0, 9, NULL); -be_define_const_str(dot_size, ".size", 1965188224u, 0, 5, &be_const_str__write); -be_define_const_str(_write, "_write", 2215462825u, 0, 6, &be_const_str_init); -be_define_const_str(init, "init", 380752755u, 0, 4, NULL); -be_define_const_str(gamma10, "gamma10", 3472052483u, 0, 7, &be_const_str_gen_cb); -be_define_const_str(gen_cb, "gen_cb", 3245227551u, 0, 6, &be_const_str_remove_rule); -be_define_const_str(remove_rule, "remove_rule", 3456211328u, 0, 11, NULL); -be_define_const_str(ctypes_bytes_dyn, "ctypes_bytes_dyn", 915205307u, 0, 16, NULL); -be_define_const_str(SERIAL_6N2, "SERIAL_6N2", 148562844u, 0, 10, &be_const_str_available); -be_define_const_str(available, "available", 1727918744u, 0, 9, &be_const_str_cb_dispatch); -be_define_const_str(cb_dispatch, "cb_dispatch", 1741510499u, 0, 11, &be_const_str_isinstance); -be_define_const_str(isinstance, "isinstance", 3669352738u, 0, 10, NULL); -be_define_const_str(copy, "copy", 3848464964u, 0, 4, &be_const_str_find); -be_define_const_str(find, "find", 3186656602u, 0, 4, NULL); -be_define_const_str(POST, "POST", 1929554311u, 0, 4, &be_const_str_write_bytes); -be_define_const_str(write_bytes, "write_bytes", 1227543792u, 0, 11, NULL); -be_define_const_str(, "", 2166136261u, 0, 0, &be_const_str_type); -be_define_const_str(type, "type", 1361572173u, 0, 4, NULL); -be_define_const_str(allocated, "allocated", 429986098u, 0, 9, &be_const_str_insert); -be_define_const_str(insert, "insert", 3332609576u, 0, 6, &be_const_str_tolower); -be_define_const_str(tolower, "tolower", 1042520049u, 0, 7, NULL); -be_define_const_str(dot_w, ".w", 1255414514u, 0, 2, &be_const_str_srand); -be_define_const_str(srand, "srand", 465518633u, 0, 5, &be_const_str_wire2); -be_define_const_str(wire2, "wire2", 3229499038u, 0, 5, NULL); -be_define_const_str(format, "format", 3114108242u, 0, 6, &be_const_str_yield); -be_define_const_str(yield, "yield", 1821831854u, 0, 5, NULL); -be_define_const_str(SERIAL_5E2, "SERIAL_5E2", 1180552854u, 0, 10, &be_const_str_reduce); -be_define_const_str(reduce, "reduce", 2002030311u, 0, 6, &be_const_str_resp_cmnd_done); -be_define_const_str(resp_cmnd_done, "resp_cmnd_done", 2601874875u, 0, 14, NULL); -be_define_const_str(abs, "abs", 709362235u, 0, 3, &be_const_str_setitem); -be_define_const_str(setitem, "setitem", 1554834596u, 0, 7, NULL); -be_define_const_str(OneWire, "OneWire", 2298990722u, 0, 7, &be_const_str_upper); -be_define_const_str(upper, "upper", 176974407u, 0, 5, NULL); -be_define_const_str(module, "module", 3617558685u, 0, 6, NULL); -be_define_const_str(counters, "counters", 4095866864u, 0, 8, &be_const_str_tag); -be_define_const_str(tag, "tag", 2516003219u, 0, 3, NULL); -be_define_const_str(tanh, "tanh", 153638352u, 0, 4, NULL); -be_define_const_str(get_string, "get_string", 4195847969u, 0, 10, &be_const_str_read12); -be_define_const_str(read12, "read12", 4291076970u, 0, 6, &be_const_str_wire_scan); -be_define_const_str(wire_scan, "wire_scan", 2671275880u, 0, 9, NULL); -be_define_const_str(seti, "seti", 1500556254u, 0, 4, NULL); -be_define_const_str(cmd, "cmd", 4136785899u, 0, 3, &be_const_str_content_send); -be_define_const_str(content_send, "content_send", 1673733649u, 0, 12, &be_const_str_global); -be_define_const_str(global, "global", 503252654u, 0, 6, &be_const_str_var); -be_define_const_str(var, "var", 2317739966u, 64, 3, NULL); -be_define_const_str(SERIAL_7N1, "SERIAL_7N1", 1891060246u, 0, 10, &be_const_str_resize); -be_define_const_str(resize, "resize", 3514612129u, 0, 6, &be_const_str_split); -be_define_const_str(split, "split", 2276994531u, 0, 5, &be_const_str_str); -be_define_const_str(str, "str", 3259748752u, 0, 3, &be_const_str_url_encode); -be_define_const_str(url_encode, "url_encode", 528392145u, 0, 10, NULL); -be_define_const_str(get_option, "get_option", 2123730033u, 0, 10, &be_const_str_listdir); -be_define_const_str(listdir, "listdir", 2005220720u, 0, 7, &be_const_str_tomap); -be_define_const_str(tomap, "tomap", 612167626u, 0, 5, NULL); -be_define_const_str(check_privileged_access, "check_privileged_access", 3692933968u, 0, 23, NULL); -be_define_const_str(pin_mode, "pin_mode", 3258314030u, 0, 8, NULL); -be_define_const_str(pin, "pin", 1866532500u, 0, 3, &be_const_str_try); -be_define_const_str(try, "try", 2887626766u, 68, 3, NULL); -be_define_const_str(_buffer, "_buffer", 2044888568u, 0, 7, &be_const_str_cos); -be_define_const_str(cos, "cos", 4220379804u, 0, 3, NULL); -be_define_const_str(dot_p, ".p", 1171526419u, 0, 2, &be_const_str_SERIAL_7O2); -be_define_const_str(SERIAL_7O2, "SERIAL_7O2", 1840580294u, 0, 10, NULL); -be_define_const_str(real, "real", 3604983901u, 0, 4, NULL); -be_define_const_str(set_timer, "set_timer", 2135414533u, 0, 9, NULL); -be_define_const_str(count, "count", 967958004u, 0, 5, &be_const_str_write); -be_define_const_str(write, "write", 3190202204u, 0, 5, NULL); -be_define_const_str(_settings_def, "_settings_def", 3775560307u, 0, 13, &be_const_str_digital_read); -be_define_const_str(digital_read, "digital_read", 3585496928u, 0, 12, NULL); -be_define_const_str(path, "path", 2223459638u, 0, 4, NULL); -be_define_const_str(delay, "delay", 1322381784u, 0, 5, &be_const_str_stop); -be_define_const_str(stop, "stop", 3411225317u, 0, 4, NULL); -be_define_const_str(AES_GCM, "AES_GCM", 3832208678u, 0, 7, NULL); -be_define_const_str(SERIAL_6O2, "SERIAL_6O2", 316486129u, 0, 10, &be_const_str_open); -be_define_const_str(open, "open", 3546203337u, 0, 4, &be_const_str_top); -be_define_const_str(top, "top", 2802900028u, 0, 3, NULL); -be_define_const_str(write_bit, "write_bit", 2660990436u, 0, 9, NULL); -be_define_const_str(state, "state", 2016490230u, 0, 5, NULL); -be_define_const_str(set_useragent, "set_useragent", 612237244u, 0, 13, &be_const_str_as); -be_define_const_str(as, "as", 1579491469u, 67, 2, NULL); -be_define_const_str(erase, "erase", 1010949589u, 0, 5, &be_const_str_has_arg); -be_define_const_str(has_arg, "has_arg", 424878688u, 0, 7, &be_const_str_map); -be_define_const_str(map, "map", 3751997361u, 0, 3, &be_const_str_on); -be_define_const_str(on, "on", 1630810064u, 0, 2, NULL); -be_define_const_str(AudioGeneratorWAV, "AudioGeneratorWAV", 2746509368u, 0, 17, &be_const_str__cb); -be_define_const_str(_cb, "_cb", 4043300367u, 0, 3, &be_const_str_decrypt); -be_define_const_str(decrypt, "decrypt", 2886974618u, 0, 7, &be_const_str_sqrt); -be_define_const_str(sqrt, "sqrt", 2112764879u, 0, 4, NULL); -be_define_const_str(SERIAL_5N1, "SERIAL_5N1", 3313031680u, 0, 10, NULL); -be_define_const_str(find_key_i, "find_key_i", 850136726u, 0, 10, NULL); -be_define_const_str(arg, "arg", 1047474471u, 0, 3, &be_const_str_depower); -be_define_const_str(depower, "depower", 3563819571u, 0, 7, &be_const_str_write_file); -be_define_const_str(write_file, "write_file", 3177658879u, 0, 10, NULL); -be_define_const_str(SERIAL_5O2, "SERIAL_5O2", 3732325060u, 0, 10, &be_const_str_get_light); -be_define_const_str(get_light, "get_light", 381930476u, 0, 9, &be_const_str_pop); -be_define_const_str(pop, "pop", 1362321360u, 0, 3, NULL); -be_define_const_str(exec_tele, "exec_tele", 1020751601u, 0, 9, NULL); -be_define_const_str(set_light, "set_light", 3176076152u, 0, 9, &be_const_str_set_timeouts); -be_define_const_str(set_timeouts, "set_timeouts", 3732850900u, 0, 12, &be_const_str_sinh); -be_define_const_str(sinh, "sinh", 282220607u, 0, 4, NULL); -be_define_const_str(AudioGenerator, "AudioGenerator", 1839297342u, 0, 14, &be_const_str_SERIAL_7E1); -be_define_const_str(SERIAL_7E1, "SERIAL_7E1", 147718061u, 0, 10, &be_const_str_getbits); -be_define_const_str(getbits, "getbits", 3094168979u, 0, 7, &be_const_str_shared_key); -be_define_const_str(shared_key, "shared_key", 2200833624u, 0, 10, &be_const_str_time_dump); -be_define_const_str(time_dump, "time_dump", 3330410747u, 0, 9, NULL); -be_define_const_str(content_button, "content_button", 1956476087u, 0, 14, &be_const_str_geti); -be_define_const_str(geti, "geti", 2381006490u, 0, 4, NULL); -be_define_const_str(arch, "arch", 2952804297u, 0, 4, &be_const_str_asin); -be_define_const_str(asin, "asin", 4272848550u, 0, 4, &be_const_str_get_free_heap); -be_define_const_str(get_free_heap, "get_free_heap", 625069757u, 0, 13, &be_const_str_resp_cmnd); +be_define_const_str(_cmd, "_cmd", 3419822142u, 0, 4, &be_const_str_begin); +be_define_const_str(begin, "begin", 1748273790u, 0, 5, &be_const_str_resp_cmnd); be_define_const_str(resp_cmnd, "resp_cmnd", 2869459626u, 0, 9, NULL); -be_define_const_str(content_flush, "content_flush", 214922475u, 0, 13, &be_const_str_millis); -be_define_const_str(millis, "millis", 1214679063u, 0, 6, &be_const_str_serial); -be_define_const_str(serial, "serial", 3687697785u, 0, 6, &be_const_str_skip); -be_define_const_str(skip, "skip", 1097563074u, 0, 4, NULL); -be_define_const_str(event, "event", 4264611999u, 0, 5, NULL); -be_define_const_str(opt_add, "+", 772578730u, 0, 1, &be_const_str_bus); -be_define_const_str(bus, "bus", 1607822841u, 0, 3, NULL); -be_define_const_str(acos, "acos", 1006755615u, 0, 4, &be_const_str_bytes); -be_define_const_str(bytes, "bytes", 1706151940u, 0, 5, &be_const_str_compile); -be_define_const_str(compile, "compile", 1000265118u, 0, 7, &be_const_str_get); -be_define_const_str(get, "get", 1410115415u, 0, 3, &be_const_str_tan); -be_define_const_str(tan, "tan", 2633446552u, 0, 3, NULL); -be_define_const_str(encrypt, "encrypt", 2194327650u, 0, 7, NULL); -be_define_const_str(cmd_res, "cmd_res", 921166762u, 0, 7, &be_const_str_collect); -be_define_const_str(collect, "collect", 2399039025u, 0, 7, NULL); -be_define_const_str(arg_size, "arg_size", 3310243257u, 0, 8, &be_const_str_reverse); -be_define_const_str(reverse, "reverse", 558918661u, 0, 7, NULL); -be_define_const_str(close, "close", 667630371u, 0, 5, &be_const_str_members); -be_define_const_str(members, "members", 937576464u, 0, 7, NULL); -be_define_const_str(assert, "assert", 2774883451u, 0, 6, &be_const_str_exec_cmd); -be_define_const_str(exec_cmd, "exec_cmd", 493567399u, 0, 8, &be_const_str_get_power); -be_define_const_str(get_power, "get_power", 3009799377u, 0, 9, &be_const_str_resp_cmnd_failed); -be_define_const_str(resp_cmnd_failed, "resp_cmnd_failed", 2136281562u, 0, 16, &be_const_str_target_search); -be_define_const_str(target_search, "target_search", 1947846553u, 0, 13, NULL); -be_define_const_str(AudioFileSource, "AudioFileSource", 2959980058u, 0, 15, &be_const_str_SERIAL_8N1); -be_define_const_str(SERIAL_8N1, "SERIAL_8N1", 2369297235u, 0, 10, &be_const_str_pi); -be_define_const_str(pi, "pi", 1213090802u, 0, 2, NULL); -be_define_const_str(add_header, "add_header", 927130612u, 0, 10, &be_const_str_list); -be_define_const_str(list, "list", 217798785u, 0, 4, &be_const_str_read_sensors); -be_define_const_str(read_sensors, "read_sensors", 892689201u, 0, 12, &be_const_str_super); -be_define_const_str(super, "super", 4152230356u, 0, 5, NULL); -be_define_const_str(has, "has", 3988721635u, 0, 3, NULL); -be_define_const_str(__upper__, "__upper__", 3612202883u, 0, 9, &be_const_str_exp); -be_define_const_str(exp, "exp", 1923516200u, 0, 3, &be_const_str_int); -be_define_const_str(int, "int", 2515107422u, 0, 3, &be_const_str_size); -be_define_const_str(size, "size", 597743964u, 0, 4, &be_const_str_for); -be_define_const_str(for, "for", 2901640080u, 54, 3, NULL); -be_define_const_str(ctypes_bytes, "ctypes_bytes", 3879019703u, 0, 12, &be_const_str_wifi); -be_define_const_str(wifi, "wifi", 120087624u, 0, 4, &be_const_str_elif); -be_define_const_str(elif, "elif", 3232090307u, 51, 4, NULL); -be_define_const_str(arg_name, "arg_name", 1345046155u, 0, 8, &be_const_str_cosh); -be_define_const_str(cosh, "cosh", 4099687964u, 0, 4, &be_const_str_lower); -be_define_const_str(lower, "lower", 3038577850u, 0, 5, &be_const_str_push); -be_define_const_str(push, "push", 2272264157u, 0, 4, &be_const_str_save); -be_define_const_str(save, "save", 3439296072u, 0, 4, NULL); -be_define_const_str(load, "load", 3859241449u, 0, 4, NULL); -be_define_const_str(SERIAL_8E2, "SERIAL_8E2", 2421454473u, 0, 10, &be_const_str_nan); -be_define_const_str(nan, "nan", 797905850u, 0, 3, &be_const_str_remove_driver); -be_define_const_str(remove_driver, "remove_driver", 1030243768u, 0, 13, &be_const_str_write8); -be_define_const_str(write8, "write8", 3133991532u, 0, 6, NULL); -be_define_const_str(_get_cb, "_get_cb", 1448849122u, 0, 7, NULL); -be_define_const_str(iter, "iter", 3124256359u, 0, 4, NULL); -be_define_const_str(_cmd, "_cmd", 3419822142u, 0, 4, &be_const_str_exists); -be_define_const_str(exists, "exists", 1002329533u, 0, 6, NULL); -be_define_const_str(AudioGeneratorMP3, "AudioGeneratorMP3", 2199818488u, 0, 17, &be_const_str__end_transmission); -be_define_const_str(_end_transmission, "_end_transmission", 3237480400u, 0, 17, NULL); -be_define_const_str(get_switch, "get_switch", 164821028u, 0, 10, NULL); -be_define_const_str(_available, "_available", 1306196581u, 0, 10, NULL); +be_define_const_str(assert, "assert", 2774883451u, 0, 6, &be_const_str_set); +be_define_const_str(set, "set", 3324446467u, 0, 3, &be_const_str_tag); +be_define_const_str(tag, "tag", 2516003219u, 0, 3, NULL); +be_define_const_str(check_privileged_access, "check_privileged_access", 3692933968u, 0, 23, &be_const_str_kv); +be_define_const_str(kv, "kv", 1497177492u, 0, 2, &be_const_str_publish); +be_define_const_str(publish, "publish", 264247304u, 0, 7, &be_const_str_read32); +be_define_const_str(read32, "read32", 1741276240u, 0, 6, NULL); +be_define_const_str(load, "load", 3859241449u, 0, 4, &be_const_str_read13); +be_define_const_str(read13, "read13", 12887293u, 0, 6, &be_const_str_search); +be_define_const_str(search, "search", 2150836393u, 0, 6, NULL); +be_define_const_str(dac_voltage, "dac_voltage", 1552257222u, 0, 11, &be_const_str_finish); +be_define_const_str(finish, "finish", 1494643858u, 0, 6, &be_const_str_hex); +be_define_const_str(hex, "hex", 4273249610u, 0, 3, &be_const_str_isinstance); +be_define_const_str(isinstance, "isinstance", 3669352738u, 0, 10, &be_const_str_rand); +be_define_const_str(rand, "rand", 2711325910u, 0, 4, NULL); +be_define_const_str(POST, "POST", 1929554311u, 0, 4, &be_const_str_SERIAL_6E2); +be_define_const_str(SERIAL_6E2, "SERIAL_6E2", 317471867u, 0, 10, NULL); +be_define_const_str(classname, "classname", 1998589948u, 0, 9, NULL); +be_define_const_str(_global_def, "_global_def", 646007001u, 0, 11, &be_const_str_open); +be_define_const_str(open, "open", 3546203337u, 0, 4, &be_const_str_redirect); +be_define_const_str(redirect, "redirect", 389758641u, 0, 8, NULL); +be_define_const_str(AES_GCM, "AES_GCM", 3832208678u, 0, 7, &be_const_str_resp_cmnd_failed); +be_define_const_str(resp_cmnd_failed, "resp_cmnd_failed", 2136281562u, 0, 16, &be_const_str_reverse_gamma10); +be_define_const_str(reverse_gamma10, "reverse_gamma10", 739112262u, 0, 15, NULL); +be_define_const_str(strftime, "strftime", 187738851u, 0, 8, NULL); +be_define_const_str(insert, "insert", 3332609576u, 0, 6, &be_const_str_false); be_define_const_str(false, "false", 184981848u, 62, 5, NULL); -be_define_const_str(settings, "settings", 1745255176u, 0, 8, &be_const_str_wd); -be_define_const_str(wd, "wd", 1531424278u, 0, 2, NULL); -be_define_const_str(SERIAL_8O2, "SERIAL_8O2", 272345123u, 0, 10, &be_const_str_rad); -be_define_const_str(rad, "rad", 1358899048u, 0, 3, NULL); -be_define_const_str(kv, "kv", 1497177492u, 0, 2, &be_const_str_toupper); -be_define_const_str(toupper, "toupper", 3691983576u, 0, 7, &be_const_str_tr); -be_define_const_str(tr, "tr", 1195724803u, 0, 2, &be_const_str_return); +be_define_const_str(arg_size, "arg_size", 3310243257u, 0, 8, &be_const_str_serial); +be_define_const_str(serial, "serial", 3687697785u, 0, 6, NULL); +be_define_const_str(OneWire, "OneWire", 2298990722u, 0, 7, &be_const_str_scale_uint); +be_define_const_str(scale_uint, "scale_uint", 3090811094u, 0, 10, NULL); be_define_const_str(return, "return", 2246981567u, 60, 6, NULL); -be_define_const_str(memory, "memory", 2229924270u, 0, 6, &be_const_str_tostring); +be_define_const_str(wire, "wire", 4082753944u, 0, 4, &be_const_str_write_bytes); +be_define_const_str(write_bytes, "write_bytes", 1227543792u, 0, 11, NULL); +be_define_const_str(_global_addr, "_global_addr", 533766721u, 0, 12, &be_const_str_exec_tele); +be_define_const_str(exec_tele, "exec_tele", 1020751601u, 0, 9, &be_const_str_target_search); +be_define_const_str(target_search, "target_search", 1947846553u, 0, 13, NULL); +be_define_const_str(gamma8, "gamma8", 3802843830u, 0, 6, &be_const_str_pi); +be_define_const_str(pi, "pi", 1213090802u, 0, 2, &be_const_str_state); +be_define_const_str(state, "state", 2016490230u, 0, 5, NULL); +be_define_const_str(depower, "depower", 3563819571u, 0, 7, &be_const_str_init); +be_define_const_str(init, "init", 380752755u, 0, 4, &be_const_str_member); +be_define_const_str(member, "member", 719708611u, 0, 6, NULL); +be_define_const_str(_end_transmission, "_end_transmission", 3237480400u, 0, 17, &be_const_str_digital_read); +be_define_const_str(digital_read, "digital_read", 3585496928u, 0, 12, &be_const_str_imin); +be_define_const_str(imin, "imin", 2714127864u, 0, 4, NULL); +be_define_const_str(hs2rgb, "hs2rgb", 1040816349u, 0, 6, &be_const_str_keys); +be_define_const_str(keys, "keys", 4182378701u, 0, 4, &be_const_str_real); +be_define_const_str(real, "real", 3604983901u, 0, 4, &be_const_str_sin); +be_define_const_str(sin, "sin", 3761252941u, 0, 3, NULL); +be_define_const_str(SERIAL_7N1, "SERIAL_7N1", 1891060246u, 0, 10, NULL); +be_define_const_str(ctypes_bytes, "ctypes_bytes", 3879019703u, 0, 12, &be_const_str_ctypes_bytes_dyn); +be_define_const_str(ctypes_bytes_dyn, "ctypes_bytes_dyn", 915205307u, 0, 16, &be_const_str_raise); +be_define_const_str(raise, "raise", 1593437475u, 70, 5, NULL); +be_define_const_str(GET, "GET", 2531704439u, 0, 3, &be_const_str__settings_def); +be_define_const_str(_settings_def, "_settings_def", 3775560307u, 0, 13, &be_const_str_read24); +be_define_const_str(read24, "read24", 1808533811u, 0, 6, NULL); +be_define_const_str(cos, "cos", 4220379804u, 0, 3, &be_const_str_remove_driver); +be_define_const_str(remove_driver, "remove_driver", 1030243768u, 0, 13, NULL); +be_define_const_str(_settings_ptr, "_settings_ptr", 1825772182u, 0, 13, &be_const_str_memory); +be_define_const_str(memory, "memory", 2229924270u, 0, 6, &be_const_str_set_auth); +be_define_const_str(set_auth, "set_auth", 1057170930u, 0, 8, NULL); +be_define_const_str(content_send_style, "content_send_style", 1087907647u, 0, 18, &be_const_str_class); +be_define_const_str(class, "class", 2872970239u, 57, 5, NULL); +be_define_const_str(SERIAL_7E2, "SERIAL_7E2", 97385204u, 0, 10, &be_const_str_shared_key); +be_define_const_str(shared_key, "shared_key", 2200833624u, 0, 10, &be_const_str_tanh); +be_define_const_str(tanh, "tanh", 153638352u, 0, 4, &be_const_str_nil); +be_define_const_str(nil, "nil", 228849900u, 63, 3, NULL); +be_define_const_str(get_power, "get_power", 3009799377u, 0, 9, &be_const_str_last_modified); +be_define_const_str(last_modified, "last_modified", 772177145u, 0, 13, &be_const_str_resolvecmnd); +be_define_const_str(resolvecmnd, "resolvecmnd", 993361485u, 0, 11, NULL); +be_define_const_str(_read, "_read", 346717030u, 0, 5, NULL); +be_define_const_str(atan, "atan", 108579519u, 0, 4, &be_const_str_content_button); +be_define_const_str(content_button, "content_button", 1956476087u, 0, 14, &be_const_str_setbits); +be_define_const_str(setbits, "setbits", 2762408167u, 0, 7, &be_const_str_upper); +be_define_const_str(upper, "upper", 176974407u, 0, 5, NULL); +be_define_const_str(contains, "contains", 1825239352u, 0, 8, &be_const_str_time_str); +be_define_const_str(time_str, "time_str", 2613827612u, 0, 8, NULL); +be_define_const_str(arch, "arch", 2952804297u, 0, 4, &be_const_str_fromptr); +be_define_const_str(fromptr, "fromptr", 666189689u, 0, 7, &be_const_str_push); +be_define_const_str(push, "push", 2272264157u, 0, 4, &be_const_str_srand); +be_define_const_str(srand, "srand", 465518633u, 0, 5, NULL); +be_define_const_str(geti, "geti", 2381006490u, 0, 4, &be_const_str_seti); +be_define_const_str(seti, "seti", 1500556254u, 0, 4, NULL); +be_define_const_str(add_cmd, "add_cmd", 3361630879u, 0, 7, &be_const_str_cmd); +be_define_const_str(cmd, "cmd", 4136785899u, 0, 3, NULL); +be_define_const_str(get_switch, "get_switch", 164821028u, 0, 10, &be_const_str_size); +be_define_const_str(size, "size", 597743964u, 0, 4, NULL); +be_define_const_str(try, "try", 2887626766u, 68, 3, NULL); +be_define_const_str(web_send, "web_send", 2989941448u, 0, 8, &be_const_str_except); +be_define_const_str(except, "except", 950914032u, 69, 6, NULL); +be_define_const_str(SERIAL_5O1, "SERIAL_5O1", 3782657917u, 0, 10, &be_const_str_SERIAL_8E2); +be_define_const_str(SERIAL_8E2, "SERIAL_8E2", 2421454473u, 0, 10, &be_const_str__available); +be_define_const_str(_available, "_available", 1306196581u, 0, 10, NULL); +be_define_const_str(codedump, "codedump", 1786337906u, 0, 8, &be_const_str_wire2); +be_define_const_str(wire2, "wire2", 3229499038u, 0, 5, NULL); +be_define_const_str(dump, "dump", 3663001223u, 0, 4, &be_const_str_exec_cmd); +be_define_const_str(exec_cmd, "exec_cmd", 493567399u, 0, 8, NULL); +be_define_const_str(add, "add", 993596020u, 0, 3, &be_const_str_exp); +be_define_const_str(exp, "exp", 1923516200u, 0, 3, &be_const_str_isrunning); +be_define_const_str(isrunning, "isrunning", 1688182268u, 0, 9, &be_const_str_remove_rule); +be_define_const_str(remove_rule, "remove_rule", 3456211328u, 0, 11, &be_const_str_run_deferred); +be_define_const_str(run_deferred, "run_deferred", 371594696u, 0, 12, &be_const_str_scan); +be_define_const_str(scan, "scan", 3974641896u, 0, 4, &be_const_str_for); +be_define_const_str(for, "for", 2901640080u, 54, 3, NULL); +be_define_const_str(set_timer, "set_timer", 2135414533u, 0, 9, &be_const_str_url_encode); +be_define_const_str(url_encode, "url_encode", 528392145u, 0, 10, NULL); +be_define_const_str(addr, "addr", 1087856498u, 0, 4, NULL); +be_define_const_str(__upper__, "__upper__", 3612202883u, 0, 9, &be_const_str_loop); +be_define_const_str(loop, "loop", 3723446379u, 0, 4, NULL); +be_define_const_str(AudioGeneratorWAV, "AudioGeneratorWAV", 2746509368u, 0, 17, &be_const_str_chars_in_string); +be_define_const_str(chars_in_string, "chars_in_string", 3148785132u, 0, 15, &be_const_str_cosh); +be_define_const_str(cosh, "cosh", 4099687964u, 0, 4, &be_const_str_import); +be_define_const_str(import, "import", 288002260u, 66, 6, NULL); +be_define_const_str(SERIAL_5N2, "SERIAL_5N2", 3363364537u, 0, 10, &be_const_str_type); +be_define_const_str(type, "type", 1361572173u, 0, 4, NULL); +be_define_const_str(clear, "clear", 1550717474u, 0, 5, NULL); +be_define_const_str(SERIAL_8N1, "SERIAL_8N1", 2369297235u, 0, 10, &be_const_str_issubclass); +be_define_const_str(issubclass, "issubclass", 4078395519u, 0, 10, &be_const_str_remove_timer); +be_define_const_str(remove_timer, "remove_timer", 4141472215u, 0, 12, &be_const_str_sinh); +be_define_const_str(sinh, "sinh", 282220607u, 0, 4, NULL); +be_define_const_str(AudioGeneratorMP3, "AudioGeneratorMP3", 2199818488u, 0, 17, &be_const_str_Wire); +be_define_const_str(Wire, "Wire", 1938276536u, 0, 4, &be_const_str_get_light); +be_define_const_str(get_light, "get_light", 381930476u, 0, 9, NULL); +be_define_const_str(get_option, "get_option", 2123730033u, 0, 10, &be_const_str_list); +be_define_const_str(list, "list", 217798785u, 0, 4, &be_const_str_stop); +be_define_const_str(stop, "stop", 3411225317u, 0, 4, &be_const_str_try_rule); +be_define_const_str(try_rule, "try_rule", 1986449405u, 0, 8, NULL); +be_define_const_str(webclient, "webclient", 4076389146u, 0, 9, NULL); +be_define_const_str(dot_p2, ".p2", 232398067u, 0, 3, &be_const_str_has); +be_define_const_str(has, "has", 3988721635u, 0, 3, NULL); +be_define_const_str(_request_from, "_request_from", 3965148604u, 0, 13, &be_const_str_setrange); +be_define_const_str(setrange, "setrange", 3794019032u, 0, 8, NULL); +be_define_const_str(I2C_Driver, "I2C_Driver", 1714501658u, 0, 10, NULL); +be_define_const_str(ceil, "ceil", 1659167240u, 0, 4, &be_const_str_else); +be_define_const_str(else, "else", 3183434736u, 52, 4, NULL); +be_define_const_str(concat, "concat", 4124019837u, 0, 6, &be_const_str_set_power); +be_define_const_str(set_power, "set_power", 549820893u, 0, 9, NULL); +be_define_const_str(tomap, "tomap", 612167626u, 0, 5, NULL); +be_define_const_str(resp_cmnd_error, "resp_cmnd_error", 2404088863u, 0, 15, NULL); +be_define_const_str(add_header, "add_header", 927130612u, 0, 10, &be_const_str_eth); +be_define_const_str(eth, "eth", 2191266556u, 0, 3, &be_const_str_write_bit); +be_define_const_str(write_bit, "write_bit", 2660990436u, 0, 9, NULL); +be_define_const_str(exists, "exists", 1002329533u, 0, 6, &be_const_str_pow); +be_define_const_str(pow, "pow", 1479764693u, 0, 3, &be_const_str_select); +be_define_const_str(select, "select", 297952813u, 0, 6, NULL); +be_define_const_str(allocated, "allocated", 429986098u, 0, 9, &be_const_str_classof); +be_define_const_str(classof, "classof", 1796577762u, 0, 7, &be_const_str_if); +be_define_const_str(if, "if", 959999494u, 50, 2, NULL); +be_define_const_str(SERIAL_5E1, "SERIAL_5E1", 1163775235u, 0, 10, &be_const_str_arg); +be_define_const_str(arg, "arg", 1047474471u, 0, 3, &be_const_str_cb_dispatch); +be_define_const_str(cb_dispatch, "cb_dispatch", 1741510499u, 0, 11, &be_const_str_response_append); +be_define_const_str(response_append, "response_append", 450346371u, 0, 15, NULL); +be_define_const_str(pin_used, "pin_used", 4033854612u, 0, 8, &be_const_str_write); +be_define_const_str(write, "write", 3190202204u, 0, 5, &be_const_str_write8); +be_define_const_str(write8, "write8", 3133991532u, 0, 6, NULL); +be_define_const_str(SERIAL_6O2, "SERIAL_6O2", 316486129u, 0, 10, &be_const_str_log); +be_define_const_str(log, "log", 1062293841u, 0, 3, NULL); +be_define_const_str(pin_mode, "pin_mode", 3258314030u, 0, 8, &be_const_str_read12); +be_define_const_str(read12, "read12", 4291076970u, 0, 6, &be_const_str_resp_cmnd_str); +be_define_const_str(resp_cmnd_str, "resp_cmnd_str", 737845590u, 0, 13, NULL); +be_define_const_str(abs, "abs", 709362235u, 0, 3, &be_const_str_digital_write); +be_define_const_str(digital_write, "digital_write", 3435877979u, 0, 13, &be_const_str_static); +be_define_const_str(static, "static", 3532702267u, 71, 6, NULL); +be_define_const_str(bytes, "bytes", 1706151940u, 0, 5, &be_const_str_find_op); +be_define_const_str(find_op, "find_op", 3766713376u, 0, 7, NULL); +be_define_const_str(call, "call", 3018949801u, 0, 4, NULL); +be_define_const_str(cmd_res, "cmd_res", 921166762u, 0, 7, NULL); +be_define_const_str(opt_eq, "==", 2431966415u, 0, 2, NULL); +be_define_const_str(save, "save", 3439296072u, 0, 4, NULL); +be_define_const_str(find_key_i, "find_key_i", 850136726u, 0, 10, NULL); +be_define_const_str(_cb, "_cb", 4043300367u, 0, 3, NULL); +be_define_const_str(Tasmota, "Tasmota", 4047617668u, 0, 7, &be_const_str_public_key); +be_define_const_str(public_key, "public_key", 4169142980u, 0, 10, NULL); +be_define_const_str(as, "as", 1579491469u, 67, 2, NULL); +be_define_const_str(dot_w, ".w", 1255414514u, 0, 2, &be_const_str_SERIAL_8O1); +be_define_const_str(SERIAL_8O1, "SERIAL_8O1", 289122742u, 0, 10, &be_const_str_compile); +be_define_const_str(compile, "compile", 1000265118u, 0, 7, &be_const_str_range); +be_define_const_str(range, "range", 4208725202u, 0, 5, NULL); +be_define_const_str(add_rule, "add_rule", 596540743u, 0, 8, NULL); +be_define_const_str(_ptr, "_ptr", 306235816u, 0, 4, &be_const_str_delay); +be_define_const_str(delay, "delay", 1322381784u, 0, 5, &be_const_str_pop); +be_define_const_str(pop, "pop", 1362321360u, 0, 3, &be_const_str_reset); +be_define_const_str(reset, "reset", 1695364032u, 0, 5, &be_const_str_wire_scan); +be_define_const_str(wire_scan, "wire_scan", 2671275880u, 0, 9, NULL); +be_define_const_str(reset_search, "reset_search", 1350414305u, 0, 12, &be_const_str_tolower); +be_define_const_str(tolower, "tolower", 1042520049u, 0, 7, NULL); +be_define_const_str(SERIAL_7O2, "SERIAL_7O2", 1840580294u, 0, 10, &be_const_str_asin); +be_define_const_str(asin, "asin", 4272848550u, 0, 4, &be_const_str_nan); +be_define_const_str(nan, "nan", 797905850u, 0, 3, NULL); +be_define_const_str(deg, "deg", 3327754271u, 0, 3, NULL); +be_define_const_str(log10, "log10", 2346846000u, 0, 5, NULL); +be_define_const_str(char, "char", 2823553821u, 0, 4, &be_const_str_get_size); +be_define_const_str(get_size, "get_size", 2803644713u, 0, 8, NULL); +be_define_const_str(opt_call, "()", 685372826u, 0, 2, &be_const_str_end); +be_define_const_str(end, "end", 1787721130u, 56, 3, NULL); +be_define_const_str(SERIAL_7N2, "SERIAL_7N2", 1874282627u, 0, 10, &be_const_str_time_dump); +be_define_const_str(time_dump, "time_dump", 3330410747u, 0, 9, NULL); +be_define_const_str(listdir, "listdir", 2005220720u, 0, 7, &be_const_str_wifi); +be_define_const_str(wifi, "wifi", 120087624u, 0, 4, NULL); +be_define_const_str(read_bytes, "read_bytes", 3576733173u, 0, 10, &be_const_str_reverse); +be_define_const_str(reverse, "reverse", 558918661u, 0, 7, NULL); +be_define_const_str(SERIAL_6E1, "SERIAL_6E1", 334249486u, 0, 10, NULL); +be_define_const_str(SERIAL_5O2, "SERIAL_5O2", 3732325060u, 0, 10, &be_const_str_SERIAL_8E1); +be_define_const_str(SERIAL_8E1, "SERIAL_8E1", 2371121616u, 0, 10, &be_const_str_asstring); +be_define_const_str(asstring, "asstring", 1298225088u, 0, 8, &be_const_str_deinit); +be_define_const_str(deinit, "deinit", 2345559592u, 0, 6, NULL); +be_define_const_str(encrypt, "encrypt", 2194327650u, 0, 7, NULL); +be_define_const_str(iter, "iter", 3124256359u, 0, 4, &be_const_str_millis); +be_define_const_str(millis, "millis", 1214679063u, 0, 6, NULL); +be_define_const_str(AudioOutput, "AudioOutput", 3257792048u, 0, 11, &be_const_str_members); +be_define_const_str(members, "members", 937576464u, 0, 7, &be_const_str_rtc); +be_define_const_str(rtc, "rtc", 1070575216u, 0, 3, NULL); +be_define_const_str(SERIAL_6N1, "SERIAL_6N1", 198895701u, 0, 10, &be_const_str__write); +be_define_const_str(_write, "_write", 2215462825u, 0, 6, &be_const_str_content_start); +be_define_const_str(content_start, "content_start", 2937509069u, 0, 13, &be_const_str_module); +be_define_const_str(module, "module", 3617558685u, 0, 6, NULL); +be_define_const_str(item, "item", 2671260646u, 0, 4, &be_const_str_remove_cmd); +be_define_const_str(remove_cmd, "remove_cmd", 3832315702u, 0, 10, NULL); +be_define_const_str(MD5, "MD5", 1935726387u, 0, 3, &be_const_str_sqrt); +be_define_const_str(sqrt, "sqrt", 2112764879u, 0, 4, NULL); +be_define_const_str(SERIAL_5N1, "SERIAL_5N1", 3313031680u, 0, 10, &be_const_str_break); +be_define_const_str(break, "break", 3378807160u, 58, 5, NULL); +be_define_const_str(map, "map", 3751997361u, 0, 3, &be_const_str_setmember); +be_define_const_str(setmember, "setmember", 1432909441u, 0, 9, &be_const_str_tostring); be_define_const_str(tostring, "tostring", 2299708645u, 0, 8, NULL); +be_define_const_str(AudioGenerator, "AudioGenerator", 1839297342u, 0, 14, &be_const_str_while); +be_define_const_str(while, "while", 231090382u, 53, 5, NULL); +be_define_const_str(event, "event", 4264611999u, 0, 5, &be_const_str_resp_cmnd_done); +be_define_const_str(resp_cmnd_done, "resp_cmnd_done", 2601874875u, 0, 14, NULL); +be_define_const_str(AudioOutputI2S, "AudioOutputI2S", 638031784u, 0, 14, &be_const_str_has_arg); +be_define_const_str(has_arg, "has_arg", 424878688u, 0, 7, NULL); +be_define_const_str(floor, "floor", 3102149661u, 0, 5, &be_const_str_read); +be_define_const_str(read, "read", 3470762949u, 0, 4, &be_const_str_remove); +be_define_const_str(remove, "remove", 3683784189u, 0, 6, NULL); +be_define_const_str(calldepth, "calldepth", 3122364302u, 0, 9, &be_const_str_lower); +be_define_const_str(lower, "lower", 3038577850u, 0, 5, &be_const_str_path); +be_define_const_str(path, "path", 2223459638u, 0, 4, NULL); +be_define_const_str(gamma10, "gamma10", 3472052483u, 0, 7, &be_const_str_get); +be_define_const_str(get, "get", 1410115415u, 0, 3, &be_const_str_elif); +be_define_const_str(elif, "elif", 3232090307u, 51, 4, NULL); +be_define_const_str(_buffer, "_buffer", 2044888568u, 0, 7, &be_const_str_exec_rules); +be_define_const_str(exec_rules, "exec_rules", 1445221092u, 0, 10, &be_const_str_pin); +be_define_const_str(pin, "pin", 1866532500u, 0, 3, NULL); +be_define_const_str(collect, "collect", 2399039025u, 0, 7, NULL); +be_define_const_str(enabled, "enabled", 49525662u, 0, 7, &be_const_str_global); +be_define_const_str(global, "global", 503252654u, 0, 6, NULL); +be_define_const_str(acos, "acos", 1006755615u, 0, 4, &be_const_str_content_stop); +be_define_const_str(content_stop, "content_stop", 658554751u, 0, 12, &be_const_str_read8); +be_define_const_str(read8, "read8", 2802788167u, 0, 5, &be_const_str_wire1); +be_define_const_str(wire1, "wire1", 3212721419u, 0, 5, NULL); +be_define_const_str(fromstring, "fromstring", 610302344u, 0, 10, &be_const_str_setitem); +be_define_const_str(setitem, "setitem", 1554834596u, 0, 7, NULL); +be_define_const_str(_debug_present, "_debug_present", 4063411725u, 0, 14, &be_const_str_erase); +be_define_const_str(erase, "erase", 1010949589u, 0, 5, &be_const_str_i2c_enabled); +be_define_const_str(i2c_enabled, "i2c_enabled", 218388101u, 0, 11, &be_const_str_resize); +be_define_const_str(resize, "resize", 3514612129u, 0, 6, NULL); +be_define_const_str(decrypt, "decrypt", 2886974618u, 0, 7, &be_const_str_escape); +be_define_const_str(escape, "escape", 2652972038u, 0, 6, &be_const_str_isnan); +be_define_const_str(isnan, "isnan", 2981347434u, 0, 5, &be_const_str_skip); +be_define_const_str(skip, "skip", 1097563074u, 0, 4, &be_const_str_var); +be_define_const_str(var, "var", 2317739966u, 64, 3, NULL); +be_define_const_str(dot_p, ".p", 1171526419u, 0, 2, &be_const_str_write_file); +be_define_const_str(write_file, "write_file", 3177658879u, 0, 10, NULL); +be_define_const_str(copy, "copy", 3848464964u, 0, 4, &be_const_str_str); +be_define_const_str(str, "str", 3259748752u, 0, 3, &be_const_str_super); +be_define_const_str(super, "super", 4152230356u, 0, 5, &be_const_str_update); +be_define_const_str(update, "update", 672109684u, 0, 6, NULL); +be_define_const_str(_def, "_def", 1985022181u, 0, 4, &be_const_str__drivers); +be_define_const_str(_drivers, "_drivers", 3260328985u, 0, 8, NULL); +be_define_const_str(imax, "imax", 3084515410u, 0, 4, NULL); +be_define_const_str(add_driver, "add_driver", 1654458371u, 0, 10, NULL); +be_define_const_str(dot_len, ".len", 850842136u, 0, 4, &be_const_str_SERIAL_6O1); +be_define_const_str(SERIAL_6O1, "SERIAL_6O1", 266153272u, 0, 10, &be_const_str_attrdump); +be_define_const_str(attrdump, "attrdump", 1521571304u, 0, 8, &be_const_str_on); +be_define_const_str(on, "on", 1630810064u, 0, 2, &be_const_str_rad); +be_define_const_str(rad, "rad", 1358899048u, 0, 3, NULL); +be_define_const_str(bus, "bus", 1607822841u, 0, 3, NULL); +be_define_const_str(yield, "yield", 1821831854u, 0, 5, NULL); +be_define_const_str(top, "top", 2802900028u, 0, 3, NULL); +be_define_const_str(get_string, "get_string", 4195847969u, 0, 10, &be_const_str_read_sensors); +be_define_const_str(read_sensors, "read_sensors", 892689201u, 0, 12, NULL); +be_define_const_str(settings, "settings", 1745255176u, 0, 8, NULL); +be_define_const_str(_get_cb, "_get_cb", 1448849122u, 0, 7, &be_const_str_int); +be_define_const_str(int, "int", 2515107422u, 0, 3, NULL); +be_define_const_str(opt_neq, "!=", 2428715011u, 0, 2, &be_const_str_gen_cb); +be_define_const_str(gen_cb, "gen_cb", 3245227551u, 0, 6, NULL); +be_define_const_str(_timers, "_timers", 2600100916u, 0, 7, &be_const_str_continue); +be_define_const_str(continue, "continue", 2977070660u, 59, 8, NULL); +be_define_const_str(SERIAL_7E1, "SERIAL_7E1", 147718061u, 0, 10, NULL); +be_define_const_str(AudioFileSource, "AudioFileSource", 2959980058u, 0, 15, &be_const_str_format); +be_define_const_str(format, "format", 3114108242u, 0, 6, NULL); +be_define_const_str(EC_C25519, "EC_C25519", 95492591u, 0, 9, &be_const_str_close); +be_define_const_str(close, "close", 667630371u, 0, 5, &be_const_str_content_flush); +be_define_const_str(content_flush, "content_flush", 214922475u, 0, 13, &be_const_str_reduce); +be_define_const_str(reduce, "reduce", 2002030311u, 0, 6, &be_const_str_tr); +be_define_const_str(tr, "tr", 1195724803u, 0, 2, NULL); +be_define_const_str(available, "available", 1727918744u, 0, 9, NULL); +be_define_const_str(traceback, "traceback", 3385188109u, 0, 9, NULL); +be_define_const_str(opt_add, "+", 772578730u, 0, 1, &be_const_str_SERIAL_8N2); +be_define_const_str(SERIAL_8N2, "SERIAL_8N2", 2386074854u, 0, 10, &be_const_str_wd); +be_define_const_str(wd, "wd", 1531424278u, 0, 2, NULL); +be_define_const_str(__iterator__, "__iterator__", 3884039703u, 0, 12, &be_const_str_fromb64); +be_define_const_str(fromb64, "fromb64", 2717019639u, 0, 7, NULL); +be_define_const_str(number, "number", 467038368u, 0, 6, &be_const_str_print); +be_define_const_str(print, "print", 372738696u, 0, 5, &be_const_str_set_useragent); +be_define_const_str(set_useragent, "set_useragent", 612237244u, 0, 13, &be_const_str_tan); +be_define_const_str(tan, "tan", 2633446552u, 0, 3, &be_const_str_do); +be_define_const_str(do, "do", 1646057492u, 65, 2, NULL); +be_define_const_str(, "", 2166136261u, 0, 0, &be_const_str_opt_connect); +be_define_const_str(opt_connect, "..", 2748622605u, 0, 2, &be_const_str__rules); +be_define_const_str(_rules, "_rules", 4266217105u, 0, 6, NULL); +be_define_const_str(dot_p1, ".p1", 249175686u, 0, 3, &be_const_str_find); +be_define_const_str(find, "find", 3186656602u, 0, 4, &be_const_str_name); +be_define_const_str(name, "name", 2369371622u, 0, 4, &be_const_str_toptr); +be_define_const_str(toptr, "toptr", 3379847454u, 0, 5, NULL); +be_define_const_str(arg_name, "arg_name", 1345046155u, 0, 8, &be_const_str_byte); +be_define_const_str(byte, "byte", 1683620383u, 0, 4, &be_const_str_gc); +be_define_const_str(gc, "gc", 1042313471u, 0, 2, NULL); +be_define_const_str(count, "count", 967958004u, 0, 5, &be_const_str_counters); +be_define_const_str(counters, "counters", 4095866864u, 0, 8, &be_const_str_tob64); +be_define_const_str(tob64, "tob64", 373777640u, 0, 5, NULL); +be_define_const_str(AudioFileSourceFS, "AudioFileSourceFS", 1839147653u, 0, 17, &be_const_str_get_free_heap); +be_define_const_str(get_free_heap, "get_free_heap", 625069757u, 0, 13, NULL); +be_define_const_str(atan2, "atan2", 3173440503u, 0, 5, NULL); +be_define_const_str(set_timeouts, "set_timeouts", 3732850900u, 0, 12, &be_const_str_toupper); +be_define_const_str(toupper, "toupper", 3691983576u, 0, 7, NULL); +be_define_const_str(_ccmd, "_ccmd", 2163421413u, 0, 5, &be_const_str_content_send); +be_define_const_str(content_send, "content_send", 1673733649u, 0, 12, &be_const_str_flush); +be_define_const_str(flush, "flush", 3002334877u, 0, 5, &be_const_str_true); +be_define_const_str(true, "true", 1303515621u, 61, 4, NULL); +be_define_const_str(detect, "detect", 8884370u, 0, 6, NULL); +be_define_const_str(SERIAL_8O2, "SERIAL_8O2", 272345123u, 0, 10, &be_const_str_split); +be_define_const_str(split, "split", 2276994531u, 0, 5, NULL); static const bstring* const m_string_table[] = { - (const bstring *)&be_const_str_pow, - (const bstring *)&be_const_str_MD5, - (const bstring *)&be_const_str_dot_p2, - (const bstring *)&be_const_str_atan, - (const bstring *)&be_const_str_SERIAL_6N1, - (const bstring *)&be_const_str_content_start, - (const bstring *)&be_const_str_SERIAL_8N2, - (const bstring *)&be_const_str_content_send_style, - NULL, - (const bstring *)&be_const_str__begin_transmission, - (const bstring *)&be_const_str_number, - (const bstring *)&be_const_str_exec_rules, - (const bstring *)&be_const_str_GET, - (const bstring *)&be_const_str_I2C_Driver, - NULL, - (const bstring *)&be_const_str_opt_neq, - (const bstring *)&be_const_str_last_modified, - (const bstring *)&be_const_str_add, - (const bstring *)&be_const_str_rtc, - (const bstring *)&be_const_str_EC_C25519, - (const bstring *)&be_const_str_ceil, - (const bstring *)&be_const_str_log, - (const bstring *)&be_const_str__global_def, - (const bstring *)&be_const_str_atan2, - (const bstring *)&be_const_str_deinit, - (const bstring *)&be_const_str_SERIAL_8O1, - (const bstring *)&be_const_str_SERIAL_6O1, - (const bstring *)&be_const_str_SERIAL_6E2, - (const bstring *)&be_const_str_gc, - (const bstring *)&be_const_str_continue, - NULL, - (const bstring *)&be_const_str_dot_p1, - (const bstring *)&be_const_str_chars_in_string, - NULL, - (const bstring *)&be_const_str_traceback, - (const bstring *)&be_const_str_calldepth, - (const bstring *)&be_const_str_finish, - (const bstring *)&be_const_str_read, - (const bstring *)&be_const_str_Tasmota, - (const bstring *)&be_const_str_SERIAL_7E2, - (const bstring *)&be_const_str___lower__, - (const bstring *)&be_const_str_member, - (const bstring *)&be_const_str_codedump, - (const bstring *)&be_const_str_opt_call, - NULL, - (const bstring *)&be_const_str_attrdump, - (const bstring *)&be_const_str_AudioOutput, - (const bstring *)&be_const_str_SERIAL_5O1, - (const bstring *)&be_const_str_public_key, - (const bstring *)&be_const_str_i2c_enabled, - (const bstring *)&be_const_str_fromptr, - (const bstring *)&be_const_str__drivers, - (const bstring *)&be_const_str_loop, - (const bstring *)&be_const_str_add_cmd, - (const bstring *)&be_const_str__settings_ptr, - (const bstring *)&be_const_str__ptr, - (const bstring *)&be_const_str_SERIAL_6E1, - (const bstring *)&be_const_str_true, - (const bstring *)&be_const_str_opt_eq, - (const bstring *)&be_const_str__timers, - (const bstring *)&be_const_str_opt_connect, - (const bstring *)&be_const_str_deg, - (const bstring *)&be_const_str_SERIAL_8E1, - NULL, - NULL, - NULL, - (const bstring *)&be_const_str_dot_len, - NULL, - (const bstring *)&be_const_str_enabled, - (const bstring *)&be_const_str_AudioOutputI2S, - (const bstring *)&be_const_str_isrunning, - (const bstring *)&be_const_str_AudioFileSourceFS, - (const bstring *)&be_const_str_dac_voltage, + (const bstring *)&be_const_str_SERIAL_6N2, (const bstring *)&be_const_str_time_reached, - (const bstring *)&be_const_str_read24, - (const bstring *)&be_const_str__global_addr, + (const bstring *)&be_const_str_SERIAL_5E2, (const bstring *)&be_const_str_SERIAL_7O1, (const bstring *)&be_const_str_dot_size, - (const bstring *)&be_const_str_gamma10, - (const bstring *)&be_const_str_ctypes_bytes_dyn, - (const bstring *)&be_const_str_SERIAL_6N2, - NULL, - (const bstring *)&be_const_str_copy, - (const bstring *)&be_const_str_POST, - (const bstring *)&be_const_str_, - (const bstring *)&be_const_str_allocated, - NULL, - (const bstring *)&be_const_str_dot_w, - (const bstring *)&be_const_str_format, - (const bstring *)&be_const_str_SERIAL_5E2, - (const bstring *)&be_const_str_abs, - (const bstring *)&be_const_str_OneWire, - (const bstring *)&be_const_str_module, - (const bstring *)&be_const_str_counters, - (const bstring *)&be_const_str_tanh, - (const bstring *)&be_const_str_get_string, - (const bstring *)&be_const_str_seti, - (const bstring *)&be_const_str_cmd, - (const bstring *)&be_const_str_SERIAL_7N1, - (const bstring *)&be_const_str_get_option, - (const bstring *)&be_const_str_check_privileged_access, - NULL, - (const bstring *)&be_const_str_pin_mode, - (const bstring *)&be_const_str_pin, - (const bstring *)&be_const_str__buffer, - (const bstring *)&be_const_str_dot_p, - (const bstring *)&be_const_str_real, - (const bstring *)&be_const_str_set_timer, - (const bstring *)&be_const_str_count, - (const bstring *)&be_const_str__settings_def, - (const bstring *)&be_const_str_path, - (const bstring *)&be_const_str_delay, - (const bstring *)&be_const_str_AES_GCM, - (const bstring *)&be_const_str_SERIAL_6O2, - (const bstring *)&be_const_str_write_bit, - (const bstring *)&be_const_str_state, - (const bstring *)&be_const_str_set_useragent, - (const bstring *)&be_const_str_erase, - (const bstring *)&be_const_str_AudioGeneratorWAV, - (const bstring *)&be_const_str_SERIAL_5N1, - (const bstring *)&be_const_str_find_key_i, - NULL, - (const bstring *)&be_const_str_arg, - (const bstring *)&be_const_str_SERIAL_5O2, - (const bstring *)&be_const_str_exec_tele, - (const bstring *)&be_const_str_set_light, - (const bstring *)&be_const_str_AudioGenerator, - (const bstring *)&be_const_str_content_button, - (const bstring *)&be_const_str_arch, - (const bstring *)&be_const_str_content_flush, - (const bstring *)&be_const_str_event, - NULL, - (const bstring *)&be_const_str_opt_add, - (const bstring *)&be_const_str_acos, - (const bstring *)&be_const_str_encrypt, - (const bstring *)&be_const_str_cmd_res, - NULL, - (const bstring *)&be_const_str_arg_size, - (const bstring *)&be_const_str_close, - (const bstring *)&be_const_str_assert, - (const bstring *)&be_const_str_AudioFileSource, - (const bstring *)&be_const_str_add_header, - NULL, - (const bstring *)&be_const_str_has, - (const bstring *)&be_const_str___upper__, - (const bstring *)&be_const_str_ctypes_bytes, - NULL, - (const bstring *)&be_const_str_arg_name, - (const bstring *)&be_const_str_load, - (const bstring *)&be_const_str_SERIAL_8E2, - (const bstring *)&be_const_str__get_cb, - (const bstring *)&be_const_str_iter, NULL, (const bstring *)&be_const_str__cmd, - (const bstring *)&be_const_str_AudioGeneratorMP3, - (const bstring *)&be_const_str_get_switch, - (const bstring *)&be_const_str__available, - (const bstring *)&be_const_str_false, - (const bstring *)&be_const_str_settings, - (const bstring *)&be_const_str_SERIAL_8O2, + (const bstring *)&be_const_str_assert, + (const bstring *)&be_const_str_check_privileged_access, + (const bstring *)&be_const_str_load, + (const bstring *)&be_const_str_dac_voltage, + (const bstring *)&be_const_str_POST, + (const bstring *)&be_const_str_classname, + (const bstring *)&be_const_str__global_def, + (const bstring *)&be_const_str_AES_GCM, + (const bstring *)&be_const_str_strftime, + (const bstring *)&be_const_str_insert, + (const bstring *)&be_const_str_arg_size, + (const bstring *)&be_const_str_OneWire, + (const bstring *)&be_const_str_return, + (const bstring *)&be_const_str_wire, + (const bstring *)&be_const_str__global_addr, + (const bstring *)&be_const_str_gamma8, + (const bstring *)&be_const_str_depower, + (const bstring *)&be_const_str__end_transmission, + (const bstring *)&be_const_str_hs2rgb, + (const bstring *)&be_const_str_SERIAL_7N1, + (const bstring *)&be_const_str_ctypes_bytes, NULL, - (const bstring *)&be_const_str_kv, - (const bstring *)&be_const_str_memory + NULL, + NULL, + (const bstring *)&be_const_str_GET, + (const bstring *)&be_const_str_cos, + NULL, + (const bstring *)&be_const_str__settings_ptr, + (const bstring *)&be_const_str_content_send_style, + (const bstring *)&be_const_str_SERIAL_7E2, + (const bstring *)&be_const_str_get_power, + (const bstring *)&be_const_str__read, + (const bstring *)&be_const_str_atan, + (const bstring *)&be_const_str_contains, + (const bstring *)&be_const_str_arch, + (const bstring *)&be_const_str_geti, + (const bstring *)&be_const_str_add_cmd, + (const bstring *)&be_const_str_get_switch, + NULL, + (const bstring *)&be_const_str_try, + NULL, + (const bstring *)&be_const_str_web_send, + (const bstring *)&be_const_str_SERIAL_5O1, + (const bstring *)&be_const_str_codedump, + (const bstring *)&be_const_str_dump, + (const bstring *)&be_const_str_add, + (const bstring *)&be_const_str_set_timer, + (const bstring *)&be_const_str_addr, + (const bstring *)&be_const_str___upper__, + (const bstring *)&be_const_str_AudioGeneratorWAV, + (const bstring *)&be_const_str_SERIAL_5N2, + (const bstring *)&be_const_str_clear, + (const bstring *)&be_const_str_SERIAL_8N1, + (const bstring *)&be_const_str_AudioGeneratorMP3, + (const bstring *)&be_const_str_get_option, + (const bstring *)&be_const_str_webclient, + (const bstring *)&be_const_str_dot_p2, + (const bstring *)&be_const_str__request_from, + NULL, + (const bstring *)&be_const_str_I2C_Driver, + NULL, + (const bstring *)&be_const_str_ceil, + (const bstring *)&be_const_str_concat, + (const bstring *)&be_const_str_tomap, + (const bstring *)&be_const_str_resp_cmnd_error, + (const bstring *)&be_const_str_add_header, + (const bstring *)&be_const_str_exists, + (const bstring *)&be_const_str_allocated, + (const bstring *)&be_const_str_SERIAL_5E1, + (const bstring *)&be_const_str_pin_used, + (const bstring *)&be_const_str_SERIAL_6O2, + (const bstring *)&be_const_str_pin_mode, + (const bstring *)&be_const_str_abs, + (const bstring *)&be_const_str_bytes, + (const bstring *)&be_const_str_call, + (const bstring *)&be_const_str_cmd_res, + (const bstring *)&be_const_str_opt_eq, + (const bstring *)&be_const_str_save, + NULL, + (const bstring *)&be_const_str_find_key_i, + (const bstring *)&be_const_str__cb, + (const bstring *)&be_const_str_Tasmota, + (const bstring *)&be_const_str_as, + (const bstring *)&be_const_str_dot_w, + (const bstring *)&be_const_str_add_rule, + (const bstring *)&be_const_str__ptr, + (const bstring *)&be_const_str_reset_search, + (const bstring *)&be_const_str_SERIAL_7O2, + (const bstring *)&be_const_str_deg, + (const bstring *)&be_const_str_log10, + (const bstring *)&be_const_str_char, + (const bstring *)&be_const_str_opt_call, + (const bstring *)&be_const_str_SERIAL_7N2, + (const bstring *)&be_const_str_listdir, + (const bstring *)&be_const_str_read_bytes, + (const bstring *)&be_const_str_SERIAL_6E1, + NULL, + (const bstring *)&be_const_str_SERIAL_5O2, + NULL, + (const bstring *)&be_const_str_encrypt, + (const bstring *)&be_const_str_iter, + (const bstring *)&be_const_str_AudioOutput, + (const bstring *)&be_const_str_SERIAL_6N1, + (const bstring *)&be_const_str_item, + (const bstring *)&be_const_str_MD5, + (const bstring *)&be_const_str_SERIAL_5N1, + (const bstring *)&be_const_str_map, + (const bstring *)&be_const_str_AudioGenerator, + (const bstring *)&be_const_str_event, + (const bstring *)&be_const_str_AudioOutputI2S, + (const bstring *)&be_const_str_floor, + (const bstring *)&be_const_str_calldepth, + (const bstring *)&be_const_str_gamma10, + (const bstring *)&be_const_str__buffer, + (const bstring *)&be_const_str_collect, + (const bstring *)&be_const_str_enabled, + (const bstring *)&be_const_str_acos, + (const bstring *)&be_const_str_fromstring, + (const bstring *)&be_const_str__debug_present, + (const bstring *)&be_const_str_decrypt, + (const bstring *)&be_const_str_dot_p, + (const bstring *)&be_const_str_copy, + (const bstring *)&be_const_str__def, + (const bstring *)&be_const_str_imax, + (const bstring *)&be_const_str_add_driver, + (const bstring *)&be_const_str_dot_len, + (const bstring *)&be_const_str_bus, + (const bstring *)&be_const_str_yield, + NULL, + (const bstring *)&be_const_str_top, + (const bstring *)&be_const_str_get_string, + NULL, + NULL, + (const bstring *)&be_const_str_settings, + NULL, + (const bstring *)&be_const_str__get_cb, + (const bstring *)&be_const_str_opt_neq, + (const bstring *)&be_const_str__timers, + (const bstring *)&be_const_str_SERIAL_7E1, + (const bstring *)&be_const_str_AudioFileSource, + (const bstring *)&be_const_str_EC_C25519, + (const bstring *)&be_const_str_available, + (const bstring *)&be_const_str_traceback, + (const bstring *)&be_const_str_opt_add, + (const bstring *)&be_const_str___iterator__, + (const bstring *)&be_const_str_number, + (const bstring *)&be_const_str_, + (const bstring *)&be_const_str_dot_p1, + (const bstring *)&be_const_str_arg_name, + (const bstring *)&be_const_str_count, + (const bstring *)&be_const_str_AudioFileSourceFS, + NULL, + (const bstring *)&be_const_str_atan2, + (const bstring *)&be_const_str_set_timeouts, + (const bstring *)&be_const_str__ccmd, + (const bstring *)&be_const_str_detect, + (const bstring *)&be_const_str_SERIAL_8O2 }; static const struct bconststrtab m_const_string_table = { - .size = 163, - .count = 327, + .size = 164, + .count = 328, .table = m_string_table }; diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_tasmota.h b/lib/libesp32/Berry/generate/be_fixed_be_class_tasmota.h index c24ab2782..c931a3bc0 100644 --- a/lib/libesp32/Berry/generate/be_fixed_be_class_tasmota.h +++ b/lib/libesp32/Berry/generate/be_fixed_be_class_tasmota.h @@ -1,94 +1,95 @@ #include "be_constobj.h" static be_define_const_map_slots(be_class_tasmota_map) { - { be_const_key(cmd_res, -1), be_const_var(0) }, - { be_const_key(run_deferred, -1), be_const_closure(run_deferred_closure) }, - { be_const_key(set_light, -1), be_const_closure(set_light_closure) }, - { be_const_key(_global_def, -1), be_const_comptr(&be_tasmota_global_struct) }, - { be_const_key(_timers, -1), be_const_var(1) }, - { be_const_key(try_rule, -1), be_const_closure(try_rule_closure) }, - { be_const_key(time_dump, -1), be_const_func(l_time_dump) }, - { be_const_key(_rules, 73), be_const_var(2) }, - { be_const_key(get_switch, 21), be_const_func(l_getswitch) }, - { be_const_key(get_option, -1), be_const_func(l_getoption) }, - { be_const_key(find_op, 4), be_const_closure(find_op_closure) }, - { be_const_key(wire1, -1), be_const_var(3) }, - { be_const_key(resp_cmnd_failed, 29), be_const_func(l_respCmndFailed) }, - { be_const_key(exec_cmd, -1), be_const_closure(exec_cmd_closure) }, - { be_const_key(gen_cb, -1), be_const_closure(gen_cb_closure) }, - { be_const_key(_cb, 57), be_const_var(4) }, - { be_const_key(hs2rgb, 71), be_const_closure(hs2rgb_closure) }, - { be_const_key(gc, -1), be_const_closure(gc_closure) }, - { be_const_key(kv, -1), be_const_closure(kv_closure) }, - { be_const_key(add_rule, -1), be_const_closure(add_rule_closure) }, - { be_const_key(scale_uint, -1), be_const_func(l_scaleuint) }, - { be_const_key(global, -1), be_const_var(5) }, - { be_const_key(rtc, 0), be_const_func(l_rtc) }, - { be_const_key(get_power, -1), be_const_func(l_getpower) }, - { be_const_key(wd, -1), be_const_var(6) }, - { be_const_key(_settings_def, -1), be_const_comptr(&be_tasmota_settings_struct) }, - { be_const_key(resp_cmnd_error, -1), be_const_func(l_respCmndError) }, - { be_const_key(read_sensors, 56), be_const_func(l_read_sensors) }, - { be_const_key(settings, -1), be_const_var(7) }, - { be_const_key(chars_in_string, -1), be_const_closure(chars_in_string_closure) }, - { be_const_key(save, -1), be_const_func(l_save) }, - { be_const_key(set_timer, -1), be_const_closure(set_timer_closure) }, - { be_const_key(time_str, -1), be_const_closure(time_str_closure) }, - { be_const_key(response_append, 14), be_const_func(l_respAppend) }, - { be_const_key(remove_driver, -1), be_const_closure(remove_driver_closure) }, - { be_const_key(i2c_enabled, -1), be_const_func(l_i2cenabled) }, - { be_const_key(web_send_decimal, -1), be_const_func(l_webSendDecimal) }, - { be_const_key(load, -1), be_const_closure(load_closure) }, - { be_const_key(_settings_ptr, 55), be_const_comptr(&Settings) }, - { be_const_key(millis, 23), be_const_func(l_millis) }, - { be_const_key(event, 67), be_const_closure(event_closure) }, - { be_const_key(cmd, -1), be_const_closure(cmd_closure) }, - { be_const_key(publish_result, 60), be_const_func(l_publish_result) }, - { be_const_key(_drivers, -1), be_const_var(8) }, - { be_const_key(get_light, 1), be_const_closure(get_light_closure) }, - { be_const_key(init, -1), be_const_closure(init_closure) }, - { be_const_key(remove_cmd, 24), be_const_closure(remove_cmd_closure) }, - { be_const_key(time_reached, -1), be_const_func(l_timereached) }, - { be_const_key(_cmd, 68), be_const_func(l_cmd) }, - { be_const_key(remove_timer, -1), be_const_closure(remove_timer_closure) }, - { be_const_key(remove_rule, 70), be_const_closure(remove_rule_closure) }, - { be_const_key(resolvecmnd, 41), be_const_func(l_resolveCmnd) }, - { be_const_key(web_send, 38), be_const_func(l_webSend) }, - { be_const_key(cb_dispatch, 6), be_const_closure(cb_dispatch_closure) }, - { be_const_key(memory, -1), be_const_func(l_memory) }, - { be_const_key(wire_scan, -1), be_const_closure(wire_scan_closure) }, - { be_const_key(strftime, 16), be_const_func(l_strftime) }, { be_const_key(resp_cmnd_done, -1), be_const_func(l_respCmndDone) }, - { be_const_key(_get_cb, -1), be_const_func(l_get_cb) }, + { be_const_key(resolvecmnd, 42), be_const_func(l_resolveCmnd) }, { be_const_key(add_driver, -1), be_const_closure(add_driver_closure) }, - { be_const_key(exec_rules, -1), be_const_closure(exec_rules_closure) }, - { be_const_key(add_cmd, -1), be_const_closure(add_cmd_closure) }, - { be_const_key(find_key_i, -1), be_const_closure(find_key_i_closure) }, - { be_const_key(log, 40), be_const_func(l_logInfo) }, - { be_const_key(wire2, -1), be_const_var(9) }, - { be_const_key(get_free_heap, -1), be_const_func(l_getFreeHeap) }, - { be_const_key(resp_cmnd_str, -1), be_const_func(l_respCmndStr) }, + { be_const_key(gc, -1), be_const_closure(gc_closure) }, + { be_const_key(find_op, -1), be_const_closure(find_op_closure) }, + { be_const_key(scale_uint, 15), be_const_func(l_scaleuint) }, + { be_const_key(try_rule, -1), be_const_closure(try_rule_closure) }, + { be_const_key(time_reached, -1), be_const_func(l_timereached) }, + { be_const_key(web_send, -1), be_const_func(l_webSend) }, + { be_const_key(eth, 21), be_const_func(l_eth) }, + { be_const_key(get_switch, 34), be_const_func(l_getswitch) }, { be_const_key(set_power, -1), be_const_func(l_setpower) }, - { be_const_key(delay, -1), be_const_func(l_delay) }, + { be_const_key(_drivers, 50), be_const_var(0) }, + { be_const_key(_rules, -1), be_const_var(1) }, + { be_const_key(_ccmd, 6), be_const_var(2) }, + { be_const_key(time_dump, -1), be_const_func(l_time_dump) }, + { be_const_key(gen_cb, 17), be_const_closure(gen_cb_closure) }, + { be_const_key(cmd_res, 20), be_const_var(3) }, + { be_const_key(set_light, 63), be_const_closure(set_light_closure) }, + { be_const_key(millis, -1), be_const_func(l_millis) }, + { be_const_key(global, -1), be_const_var(4) }, + { be_const_key(exec_tele, 67), be_const_closure(exec_tele_closure) }, + { be_const_key(_settings_ptr, -1), be_const_comptr(&Settings) }, + { be_const_key(get_power, -1), be_const_func(l_getpower) }, + { be_const_key(_cb, 57), be_const_var(5) }, + { be_const_key(save, -1), be_const_func(l_save) }, + { be_const_key(run_deferred, -1), be_const_closure(run_deferred_closure) }, + { be_const_key(i2c_enabled, 9), be_const_func(l_i2cenabled) }, + { be_const_key(remove_driver, -1), be_const_closure(remove_driver_closure) }, + { be_const_key(event, -1), be_const_closure(event_closure) }, + { be_const_key(find_key_i, -1), be_const_closure(find_key_i_closure) }, + { be_const_key(web_send_decimal, -1), be_const_func(l_webSendDecimal) }, + { be_const_key(get_free_heap, 3), be_const_func(l_getFreeHeap) }, + { be_const_key(wire_scan, -1), be_const_closure(wire_scan_closure) }, + { be_const_key(init, -1), be_const_closure(init_closure) }, + { be_const_key(wd, -1), be_const_var(6) }, + { be_const_key(_debug_present, -1), be_const_var(7) }, + { be_const_key(time_str, 45), be_const_closure(time_str_closure) }, + { be_const_key(remove_rule, 71), be_const_closure(remove_rule_closure) }, + { be_const_key(memory, 62), be_const_func(l_memory) }, { be_const_key(wifi, -1), be_const_func(l_wifi) }, - { be_const_key(yield, -1), be_const_func(l_yield) }, + { be_const_key(get_option, 44), be_const_func(l_getoption) }, + { be_const_key(rtc, -1), be_const_func(l_rtc) }, + { be_const_key(load, 72), be_const_closure(load_closure) }, + { be_const_key(chars_in_string, -1), be_const_closure(chars_in_string_closure) }, + { be_const_key(cmd, -1), be_const_closure(cmd_closure) }, + { be_const_key(publish, 43), be_const_func(l_publish) }, + { be_const_key(resp_cmnd_error, 18), be_const_func(l_respCmndError) }, + { be_const_key(add_cmd, -1), be_const_closure(add_cmd_closure) }, + { be_const_key(_settings_def, -1), be_const_comptr(&be_tasmota_settings_struct) }, + { be_const_key(strftime, 4), be_const_func(l_strftime) }, + { be_const_key(add_rule, 41), be_const_closure(add_rule_closure) }, + { be_const_key(wire2, -1), be_const_var(8) }, + { be_const_key(settings, -1), be_const_var(9) }, + { be_const_key(exec_rules, -1), be_const_closure(exec_rules_closure) }, + { be_const_key(cb_dispatch, -1), be_const_closure(cb_dispatch_closure) }, + { be_const_key(yield, 68), be_const_func(l_yield) }, + { be_const_key(_get_cb, 75), be_const_func(l_get_cb) }, + { be_const_key(wire1, 33), be_const_var(10) }, + { be_const_key(resp_cmnd, -1), be_const_func(l_respCmnd) }, + { be_const_key(resp_cmnd_failed, 16), be_const_func(l_respCmndFailed) }, + { be_const_key(_global_addr, -1), be_const_comptr(&TasmotaGlobal) }, + { be_const_key(hs2rgb, -1), be_const_closure(hs2rgb_closure) }, + { be_const_key(resp_cmnd_str, 76), be_const_func(l_respCmndStr) }, + { be_const_key(_global_def, -1), be_const_comptr(&be_tasmota_global_struct) }, + { be_const_key(kv, 74), be_const_closure(kv_closure) }, + { be_const_key(delay, -1), be_const_func(l_delay) }, + { be_const_key(remove_cmd, 19), be_const_closure(remove_cmd_closure) }, + { be_const_key(set_timer, -1), be_const_closure(set_timer_closure) }, + { be_const_key(_cmd, 54), be_const_func(l_cmd) }, + { be_const_key(publish_result, -1), be_const_func(l_publish_result) }, + { be_const_key(log, -1), be_const_func(l_logInfo) }, { be_const_key(arch, -1), be_const_func(l_arch) }, - { be_const_key(resp_cmnd, 69), be_const_func(l_respCmnd) }, - { be_const_key(_global_addr, 26), be_const_comptr(&TasmotaGlobal) }, - { be_const_key(publish, -1), be_const_func(l_publish) }, - { be_const_key(_ccmd, -1), be_const_var(10) }, - { be_const_key(eth, -1), be_const_func(l_eth) }, - { be_const_key(exec_tele, -1), be_const_closure(exec_tele_closure) }, + { be_const_key(remove_timer, 66), be_const_closure(remove_timer_closure) }, + { be_const_key(_timers, -1), be_const_var(11) }, + { be_const_key(read_sensors, -1), be_const_func(l_read_sensors) }, + { be_const_key(exec_cmd, -1), be_const_closure(exec_cmd_closure) }, + { be_const_key(response_append, -1), be_const_func(l_respAppend) }, + { be_const_key(get_light, -1), be_const_closure(get_light_closure) }, }; static be_define_const_map( be_class_tasmota_map, - 78 + 79 ); BE_EXPORT_VARIABLE be_define_const_class( be_class_tasmota, - 11, + 12, NULL, Tasmota ); diff --git a/lib/libesp32/Berry/src/be_constobj.h b/lib/libesp32/Berry/src/be_constobj.h index a565d83f9..0e8f1081c 100644 --- a/lib/libesp32/Berry/src/be_constobj.h +++ b/lib/libesp32/Berry/src/be_constobj.h @@ -217,6 +217,13 @@ const bntvmodule be_native_module(_module) = { \ .data = _items \ } +#define be_nested_str_literal(_str) \ + { \ + { .s=(be_nested_const_str(_str, 0, sizeof(_str)-1 )) \ + }, \ + BE_STRING \ + } + #define be_nested_string(_str, _hash, _len) \ { \ { .s=(be_nested_const_str(_str, _hash, _len )) \ diff --git a/lib/libesp32/Berry/src/be_solidifylib.c b/lib/libesp32/Berry/src/be_solidifylib.c index c91bc22a5..ec0b60ca1 100644 --- a/lib/libesp32/Berry/src/be_solidifylib.c +++ b/lib/libesp32/Berry/src/be_solidifylib.c @@ -121,9 +121,10 @@ static void m_solidify_bvalue(bvm *vm, bvalue * value, const char *classname, co } be_pushstring(vm, str(var_tostr(value))); be_toescape(vm, -1, 'u'); - logfmt("be_nested_string(%s", be_tostring(vm, -1)); - be_pop(vm, 1); - logfmt(", %i, %zu)", be_strhash(var_tostr(value)), len >= 255 ? 255 : len); + logfmt("be_nested_str_literal(%s)", be_tostring(vm, -1)); + // logfmt("be_nested_string(%s", be_tostring(vm, -1)); + // be_pop(vm, 1); + // logfmt(", %i, %zu)", be_strhash(var_tostr(value)), len >= 255 ? 255 : len); } break; case BE_CLOSURE: From 51e99fe4af7a31ebff61de34b754b08aac51fe48 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sun, 21 Nov 2021 23:17:45 +0100 Subject: [PATCH 084/185] Berry fix raise counter --- lib/libesp32/Berry/src/be_exec.c | 3 +++ lib/libesp32/Berry/src/be_vm.c | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/libesp32/Berry/src/be_exec.c b/lib/libesp32/Berry/src/be_exec.c index 8ed0bc8f1..7b741e4ff 100644 --- a/lib/libesp32/Berry/src/be_exec.c +++ b/lib/libesp32/Berry/src/be_exec.c @@ -74,6 +74,9 @@ struct filebuf { void be_throw(bvm *vm, int errorcode) { +#if BE_USE_PERF_COUNTERS + vm->counter_exc++; +#endif if (vm->errjmp) { vm->errjmp->status = errorcode; exec_throw(vm->errjmp); diff --git a/lib/libesp32/Berry/src/be_vm.c b/lib/libesp32/Berry/src/be_vm.c index fabba9220..6f30835d5 100644 --- a/lib/libesp32/Berry/src/be_vm.c +++ b/lib/libesp32/Berry/src/be_vm.c @@ -1019,9 +1019,6 @@ newframe: /* a new call frame */ dispatch(); } opcase(RAISE): { -#if BE_USE_PERF_COUNTERS - vm->counter_exc++; -#endif if (IGET_RA(ins) < 2) { /* A==2 means no arguments are passed to RAISE, i.e. rethrow with current exception */ bvalue *top = vm->top; top[0] = *RKB(); /* push the exception value to top */ From a1720b2ba60d16bca49fd15e191e68180f3c1fcd Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Mon, 22 Nov 2021 12:19:28 +0100 Subject: [PATCH 085/185] Fix NeoPool compile error --- tasmota/xsns_83_neopool.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xsns_83_neopool.ino b/tasmota/xsns_83_neopool.ino index 18d7a7ee7..5f0e96292 100644 --- a/tasmota/xsns_83_neopool.ino +++ b/tasmota/xsns_83_neopool.ino @@ -598,7 +598,7 @@ struct { const uint16_t type; union { NeoPoolRegBlock block; - NeoPoolRegList list[]; + NeoPoolRegList *list; }; } NeoPoolReg[] = { // 6 entries so using 250ms poll interval we are through in 1,5 for all register From 8ca727a5237c1fa6c54e5d8c75d132400096eebc Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 22 Nov 2021 12:21:07 +0100 Subject: [PATCH 086/185] Fix SSPM Gui energy display --- tasmota/xdrv_86_esp32_sonoff_spm.ino | 95 ++++++++++++++-------------- 1 file changed, 46 insertions(+), 49 deletions(-) diff --git a/tasmota/xdrv_86_esp32_sonoff_spm.ino b/tasmota/xdrv_86_esp32_sonoff_spm.ino index f2d83439e..a786a5913 100644 --- a/tasmota/xdrv_86_esp32_sonoff_spm.ino +++ b/tasmota/xdrv_86_esp32_sonoff_spm.ino @@ -34,7 +34,6 @@ * Each SPM-4Relay has 4 bistable relays with their own CSE7761 energy monitoring device handled by an ARM processor. * Green led is controlled by ARM processor indicating SD-Card access. * ESP32 is used as interface between eWelink and ARM processor in SPM-Main unit communicating over proprietary serial protocol. - * Inductive/Capacitive loads are not reported correctly. * Power on sequence for two SPM-4Relay modules is 00-00-15-10-(0F)-(13)-(13)-(19)-0C-09-04-09-04-0B-0B * * Tasmota POC1: @@ -45,9 +44,9 @@ * * Tasmota POC2: * Ethernet support. + * Gui optimized for energy display. * * Todo: - * Gui optimization for energy display. * Gui for Overload Protection entry (is handled by ARM processor). * Gui for Scheduling entry (is handled by ARM processor). * Yellow led functionality. @@ -548,11 +547,13 @@ void SSPMHandleReceivedData(void) { /* 0x04 - Overload Protection 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 AA 55 01 8b 34 32 37 39 37 34 13 4b 35 36 37 80 04 00 02 00 00 06 98 06 - Marker |Module id |Ac|Cm|Size | |Ch|Ra|Max P |Min P |Max U |Min U |Max I |De|Ix|Chksm| - | | | 4400W| 0.1W| 240V| 0.1V| 20A| | + Marker |Module id |Ac|Cm|Size | |Ix|Chksm| + AA 55 01 6B 7E 32 37 39 37 34 13 4B 35 36 37 80 04 00 35 00 07 00 11 30 00 00 00 0A 00 F0 00 00 00 0A 00 14 00 00 00 11 30 00 00 00 0A 00 F0 00 00 00 0A 00 14 00 00 00 11 30 00 00 00 0A 00 F0 00 00 00 0A 00 14 00 00 07 8A 86 + Marker |Module id |Ac|Cm|Size | |Ch|Ra|Max P |Min P |Max U |Min U |Max I |De|Ix|Chksm| + | | | 4400W| 0.1W| 240V| 0.1V| 20A| | */ if (0x02 == Sspm->expected_bytes) { @@ -650,7 +651,10 @@ void SSPMHandleReceivedData(void) { uint32_t total_energy = 0; uint32_t entries = (Sspm->expected_bytes - 22) / 2; for (uint32_t i = 0; i < entries; i++) { - total_energy += (SspmBuffer[41 + (i*2)] << 8) + SspmBuffer[42 + (i*2)]; + uint32_t today_energy = (SspmBuffer[41 + (i*2)] << 8) + SspmBuffer[42 + (i*2)]; + if (today_energy != 28702) { // Unknown why sometimes 0x701E (=28702kWh) pops up + total_energy += today_energy; + } } uint32_t channel = SspmBuffer[32]; for (uint32_t module = 0; module < Sspm->module_max; module++) { @@ -687,24 +691,6 @@ void SSPMHandleReceivedData(void) { |Ch|Curre|Voltage |ActivePo|Reactive|Apparent|??| Values are XX XX - number XX - decimals - - - - Curr Voltag Active Reacti Appare - 0 1 2 3 4 5 6 7 8 910111213141516171819202122232425262728293031 3233 343536 373839 404142 434445 46 47 4849 - AA55010000000000000000000000000006001C8B343237393734134B35363708 000A 00E05B 001817 00013B 001825 4B BC 3DDA 0.100A 224.91V 24.23W <-- 25W bulb - AA55010000000000000000000000000006001C8B343237393734134B35363708 000A 00E115 00181A 00013D 001823 4B BE 6209 - AA55010000000000000000000000000006001C8B343237393734134B35363708 0044 00E260 009C1C 000000 009C1B 00 36 FD69 0.680A 226.96V 156.28W <-- 150W bulb - - AA55010000000000000000000000000006001C8B343237393734134B35363708 0054 00E134 007525 00220A 00BD5D 20 34 55D6 - AA55010000000000000000000000000006001C8B343237393734134B35363708 0054 00E10A 007519 002126 00BD27 20 36 77EA - AA55010000000000000000000000000006001C8B343237393734134B35363708 0053 00DE40 00731F 001604 00B952 4B 12 9255 - - AA55010000000000000000000000000006001C8B343237393734134B35363708 075B 00D502 06940F 001863 069830 4B 1C E0DE - - AA55010000000000000000000000000006001c8b343237393734134b35363708 0044 00e025 009920 00010f 00993b 00 b3 07 a2 0.68A 223.25V 152.66W 0.54 Rea 152.5 Schijn - - */ { uint32_t channel = 0; @@ -764,6 +750,8 @@ void SSPMHandleReceivedData(void) { 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 13 00 24 6b 7e 32 37 39 37 34 13 4b 35 36 37 04 00 00 00 82 01 00 00 14 00 00 0a 00 f0 00 00 00 0a 11 30 00 00 00 0a 02 8f cd AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 13 00 24 8b 34 32 37 39 37 34 13 4b 35 36 37 04 00 00 00 82 01 00 00 14 00 00 0a 00 f0 00 00 00 0a 11 30 00 00 00 0a 02 a0 6f + Marker | |Ac|Cm|Size |Module id |Ch| |Max I|Min I|Max U |Min U |Max P |Min P |Ix|Chksm| + | 20A| 0.1A| 240V| 0.1V| 4400W| 0.1W| */ if ((0x24 == Sspm->expected_bytes) && (Sspm->module_max < SSPM_MAX_MODULES)) { memcpy(Sspm->module[1], Sspm->module[0], (SSPM_MAX_MODULES -1) * SSPM_MODULE_NAME_SIZE); @@ -855,9 +843,9 @@ void SSPMInit(void) { digitalWrite(SSPM_GPIO_ARM_RESET, 1); if (0 == Settings->flag2.voltage_resolution) { - Settings->flag2.voltage_resolution = 1; // SPM has only 2 decimals - Settings->flag2.current_resolution = 2; // SPM has only 2 decimals - Settings->flag2.wattage_resolution = 2; // SPM has only 2 decimals + Settings->flag2.voltage_resolution = 1; // SPM has 2 decimals but this keeps the gui clean + Settings->flag2.current_resolution = 2; // SPM has 2 decimals + Settings->flag2.wattage_resolution = 1; // SPM has 2 decimals but this keeps the gui clean Settings->flag2.energy_resolution = 0; // SPM has no decimals on total energy } @@ -1019,29 +1007,36 @@ bool SSPMButton(void) { return result; } -const char kSSPMEnergyPhases[] PROGMEM = "%*_f / %*_f / %*_f / %*_f|[%*_f,%*_f,%*_f,%*_f]"; +const uint16_t SSPM_SIZE = 128; +const char kSSPMEnergyPhases[] PROGMEM = "%*_f
%*_f%*_f%*_f|[%*_f,%*_f,%*_f,%*_f]"; char* SSPMEnergyFormat(char* result, float* input, uint32_t resolution, bool json) { - char layout[32]; + char layout[100]; GetTextIndexed(layout, sizeof(layout), json, kSSPMEnergyPhases); - ext_snprintf_P(result, FLOATSZ * 4, layout, resolution, &input[0], resolution, &input[1], resolution, &input[2], resolution, &input[3]); + ext_snprintf_P(result, SSPM_SIZE, layout, resolution, &input[0], resolution, &input[1], resolution, &input[2], resolution, &input[3]); return result; } -const char HTTP_SSPMENERGY_SNS[] PROGMEM = - "{s}" D_POWERUSAGE_APPARENT "{m}%s " D_UNIT_VA "{e}" - "{s}" D_POWERUSAGE_REACTIVE "{m}%s " D_UNIT_VAR "{e}" - "{s}" D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; // {s} =
, {m} = , {e} =
%s" D_UNIT_VOLT "{e}"; +const char HTTP_SSPM_CURRENT[] PROGMEM = + "{s}" D_CURRENT "%s" D_UNIT_AMPERE "{e}"; +const char HTTP_SSPM_POWER[] PROGMEM = + "{s}" D_POWERUSAGE_ACTIVE "%s" D_UNIT_WATT "{e}"; +const char HTTP_SSPM_ENERGY[] PROGMEM = + "{s}" D_POWERUSAGE_APPARENT "%s" D_UNIT_VA "{e}" + "{s}" D_POWERUSAGE_REACTIVE "%s" D_UNIT_VAR "{e}" + "{s}" D_ENERGY_TOTAL "%s" D_UNIT_KILOWATTHOUR "{e}"; // {s} =
, {m} = , {e} =
{t}{s}")); // First column is empty ({t} = , {s} = ) + char value_chr[SSPM_SIZE]; + WSContentSend_PD(HTTP_SSPM_VOLTAGE, SSPMEnergyFormat(value_chr, Sspm->voltage[module], Settings->flag2.voltage_resolution, json)); + WSContentSend_PD(HTTP_SSPM_CURRENT, SSPMEnergyFormat(value_chr, Sspm->current[module], Settings->flag2.current_resolution, json)); + WSContentSend_PD(HTTP_SSPM_POWER, SSPMEnergyFormat(value_chr, Sspm->active_power[module], Settings->flag2.wattage_resolution, json)); + char valu2_chr[SSPM_SIZE]; + char valu3_chr[SSPM_SIZE]; + WSContentSend_PD(HTTP_SSPM_ENERGY, SSPMEnergyFormat(value_chr, Sspm->apparent_power[module], Settings->flag2.wattage_resolution, json), + SSPMEnergyFormat(valu2_chr, Sspm->reactive_power[module], Settings->flag2.wattage_resolution, json), + SSPMEnergyFormat(valu3_chr, Sspm->total[module], Settings->flag2.energy_resolution, json)); + WSContentSend_P(PSTR("
) + for (uint32_t i = 0; i < 4; i++) { + WSContentSend_P(PSTR("L%d"), relay_base +i); + } + WSContentSend_P(PSTR("{e}")); // Last column is units ({e} =
{t}")); // {t} = - Define for next FUNC_WEB_SENSOR } } @@ -1123,8 +1123,7 @@ void CmndSSPMScan(void) { * Interface \*********************************************************************************************/ -bool Xdrv86(uint8_t function) -{ +bool Xdrv86(uint8_t function) { bool result = false; if (FUNC_INIT == function) { @@ -1141,8 +1140,6 @@ bool Xdrv86(uint8_t function) case FUNC_SET_DEVICE_POWER: result = SSPMSetDevicePower(); break; - case FUNC_EVERY_SECOND: - break; case FUNC_JSON_APPEND: SSPMEnergyShow(true); break; From da460d5d7a52469dae78b1a4d4227cc4da3a568f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 22 Nov 2021 12:30:08 +0100 Subject: [PATCH 087/185] Fix L indexes --- tasmota/xdrv_86_esp32_sonoff_spm.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_86_esp32_sonoff_spm.ino b/tasmota/xdrv_86_esp32_sonoff_spm.ino index a786a5913..ff3e114a2 100644 --- a/tasmota/xdrv_86_esp32_sonoff_spm.ino +++ b/tasmota/xdrv_86_esp32_sonoff_spm.ino @@ -1065,7 +1065,7 @@ void SSPMEnergyShow(bool json) { uint32_t module = Sspm->rotate >> 2; uint32_t relay_base = module * 4; WSContentSend_P(PSTR("
{t}{s}")); // First column is empty ({t} = , {s} = ) From bba8cd2fa033c1d2d56dd24b081c8efb36a28175 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Mon, 22 Nov 2021 12:42:25 +0100 Subject: [PATCH 088/185] Core 2.0.1.1 --- platformio_tasmota32.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index 4a5299368..f832417ea 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -33,7 +33,7 @@ build_flags = ${esp_defaults.build_flags} [core32] platform = https://github.com/platformio/platform-espressif32.git#feature/arduino-idf-master -platform_packages = framework-arduinoespressif32 @ https://github.com/tasmota/arduino-esp32/releases/download/2.0.1/framework-arduinoespressif32-release_IDF4.4.tar.gz +platform_packages = framework-arduinoespressif32 @ https://github.com/tasmota/arduino-esp32/releases/download/2.0.1.1/framework-arduinoespressif32-release_IDF4.4.tar.gz platformio/tool-esptoolpy @ https://github.com/tasmota/esptool/releases/download/v3.2/esptool-v3.2.zip platformio/tool-mklittlefs @ ~1.203.200522 build_unflags = ${esp32_defaults.build_unflags} @@ -42,7 +42,7 @@ build_flags = ${esp32_defaults.build_flags} [core32solo1] platform = https://github.com/platformio/platform-espressif32.git#feature/arduino-idf-master -platform_packages = framework-arduinoespressif32 @ https://github.com/tasmota/arduino-esp32/releases/download/2.0.1/framework-arduinoespressif32-solo1-release_IDF4.4.tar.gz +platform_packages = framework-arduinoespressif32 @ https://github.com/tasmota/arduino-esp32/releases/download/2.0.1.1/framework-arduinoespressif32-solo1-release_IDF4.4.tar.gz platformio/tool-esptoolpy @ https://github.com/tasmota/esptool/releases/download/v3.2/esptool-v3.2.zip platformio/tool-mklittlefs @ ~1.203.200522 build_unflags = ${esp32_defaults.build_unflags} From db68d6783a8a28b80273e77f82d4e279379faa67 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 22 Nov 2021 12:52:38 +0100 Subject: [PATCH 089/185] PR Template ESP32 V.2.0.1.1 --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 2f3081d31..4a15daa5c 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -7,7 +7,7 @@ - [ ] Only relevant files were touched - [ ] Only one feature/fix was added per PR and the code change compiles without warnings - [ ] The code change is tested and works with Tasmota core ESP8266 V.2.7.4.9 - - [ ] The code change is tested and works with Tasmota core ESP32 V.2.0.1 + - [ ] The code change is tested and works with Tasmota core ESP32 V.2.0.1.1 - [ ] I accept the [CLA](https://github.com/arendst/Tasmota/blob/development/CONTRIBUTING.md#contributor-license-agreement-cla). _NOTE: The code change must pass CI tests. **Your PR cannot be merged unless tests pass**_ From cfaf0b244888def11a091975bf4e8871a68cd4fe Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 22 Nov 2021 13:42:52 +0100 Subject: [PATCH 090/185] ESP32 I2C clock fix with core 2.0.1.1 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a53c17c1..28a9eebc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,10 +18,12 @@ All notable changes to this project will be documented in this file. - Removed ILI9488 driver in favor of Unversal Display Driver - IRremoteESP8266 library from v2.7.20 to v2.8.0 (#13738) - Ethernet hostname ending in ``_eth`` to ``-eth`` according to RFC952 +- ESP32 core library from v2.0.1 to v2.0.1.1 (#13768) ### Fixed - ESP32 analog NTC temperature calculation (#13703) - ESP32 ethernet broken by core 2.x +- ESP32 I2C clock stretch issue (#13768) ### Removed - ILI9488 driver in favour of Universal Display driver (#13719) From 3cb48f1f0878acf9d59dee48f72a0fecb88f6aee Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 22 Nov 2021 15:58:36 +0100 Subject: [PATCH 091/185] Fix ESP32 OneWire Fix ESP32 OneWire to work with Core 2.x (#13666) --- .../OneWire.h | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/OneWire.h b/lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/OneWire.h index eb20f2b20..edb31d1eb 100644 --- a/lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/OneWire.h +++ b/lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/OneWire.h @@ -211,12 +211,16 @@ void directModeInput(IO_REG_TYPE pin) ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown); } #elif ESP_IDF_VERSION_MAJOR > 3 // ESP32-S2 needs IDF 4.2 or later - uint32_t rtc_reg(rtc_io_desc[pin].reg); + int rtcio_num = rtc_io_number_get((gpio_num_t)pin); - if ( rtc_reg ) // RTC pins PULL settings - { - ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[pin].mux); - ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[pin].pullup | rtc_io_desc[pin].pulldown); + if (rtcio_num >= 0) { + uint32_t rtc_reg(rtc_io_desc[rtcio_num].reg); + + if ( rtc_reg ) // RTC pins PULL settings + { + ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtcio_num].mux); + ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtcio_num].pullup | rtc_io_desc[rtcio_num].pulldown); + } } #endif @@ -253,12 +257,16 @@ void directModeOutput(IO_REG_TYPE pin) ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown); } #elif ESP_IDF_VERSION_MAJOR > 3 // ESP32-S2 needs IDF 4.2 or later - uint32_t rtc_reg(rtc_io_desc[pin].reg); + int rtcio_num = rtc_io_number_get((gpio_num_t)pin); - if ( rtc_reg ) // RTC pins PULL settings - { - ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[pin].mux); - ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[pin].pullup | rtc_io_desc[pin].pulldown); + if (rtcio_num >= 0) { + uint32_t rtc_reg(rtc_io_desc[rtcio_num].reg); + + if ( rtc_reg ) // RTC pins PULL settings + { + ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtcio_num].mux); + ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtcio_num].pullup | rtc_io_desc[rtcio_num].pulldown); + } } #endif From e1c88eb5e1ce348150aac03de324e65e65129450 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 22 Nov 2021 16:08:24 +0100 Subject: [PATCH 092/185] Fix WS2812 StepPixels range check --- tasmota/xlgt_01_ws2812.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/xlgt_01_ws2812.ino b/tasmota/xlgt_01_ws2812.ino index bc8dd5f85..3a9e396f3 100644 --- a/tasmota/xlgt_01_ws2812.ino +++ b/tasmota/xlgt_01_ws2812.ino @@ -667,8 +667,8 @@ void CmndPixels(void) void CmndStepPixels(void) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= WS2812_MAX_LEDS)) { - Settings->light_step_pixels = XdrvMailbox.payload; + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 255)) { + Settings->light_step_pixels = (XdrvMailbox.payload > WS2812_MAX_LEDS) ? WS2812_MAX_LEDS : XdrvMailbox.payload; Ws2812Clear(); Light.update = true; } From 0f18553237b4a2bf534ac4b5eab62d0b7f9f2085 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 22 Nov 2021 16:20:26 +0100 Subject: [PATCH 093/185] Remove Tasmota Gratuitous ARP code for ESP32 Remove Tasmota Gratuitous ARP code for ESP32 as it is performed by core/idf --- tasmota/support_tasmota.ino | 2 ++ tasmota/support_wifi.ino | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 76db6006f..de4a0f360 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -994,8 +994,10 @@ void PerformEverySecond(void) } } +#ifdef ESP8266 // Wifi keep alive to send Gratuitous ARP wifiKeepAlive(); +#endif WifiPollNtp(); diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index bf80f579e..05072542a 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -668,6 +668,7 @@ void EspRestart(void) } } +#ifdef ESP8266 // // Gratuitous ARP, backported from https://github.com/esp8266/Arduino/pull/6889 // @@ -715,6 +716,7 @@ void wifiKeepAlive(void) { SetNextTimeInterval(wifi_timer, wifiTimerSec * 1000); } } +#endif // ESP8266 void WifiPollNtp() { static uint8_t ntp_sync_minute = 0; From bb6bc41cb01a51819e145f7a72c8d3d62c526965 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 22 Nov 2021 18:06:57 +0100 Subject: [PATCH 094/185] Add more information --- tasmota/xdrv_86_esp32_sonoff_spm.ino | 65 +++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 12 deletions(-) diff --git a/tasmota/xdrv_86_esp32_sonoff_spm.ino b/tasmota/xdrv_86_esp32_sonoff_spm.ino index ff3e114a2..e26c214c6 100644 --- a/tasmota/xdrv_86_esp32_sonoff_spm.ino +++ b/tasmota/xdrv_86_esp32_sonoff_spm.ino @@ -88,6 +88,13 @@ * relay = 0 to 127 Relays \*********************************************************************************************/ +#define SSPM_JSON_ENERGY_TODAY // Show JSON energy today +#define SSPM_JSON_ENERGY_YESTERDAY // Show JSON energy yesterday + +/*********************************************************************************************\ + * Fixed defines - Do not change +\*********************************************************************************************/ + #define XDRV_86 86 #define SSPM_MAX_MODULES 7 // Currently supports up to 7 SPM-4RELAY units for a total of 28 relays restricted by power_t size @@ -151,7 +158,9 @@ typedef struct { float apparent_power[SSPM_MAX_MODULES][4]; // 123.12 VA float reactive_power[SSPM_MAX_MODULES][4]; // 123.12 VAr float power_factor[SSPM_MAX_MODULES][4]; // 0.12 - float total[SSPM_MAX_MODULES][4]; // 12345 kWh total energy + float energy_today[SSPM_MAX_MODULES][4]; // 12345 kWh + float energy_yesterday[SSPM_MAX_MODULES][4]; // 12345 kWh + float energy_total[SSPM_MAX_MODULES][4]; // 12345 kWh total energy since last 6 month!!! uint32_t timeout; power_t old_power; @@ -648,18 +657,24 @@ void SSPMHandleReceivedData(void) { 42 67 46 */ { - uint32_t total_energy = 0; + uint32_t energy_today = 0; + uint32_t energy_yesterday = 0; + uint32_t energy_total = 0; uint32_t entries = (Sspm->expected_bytes - 22) / 2; + for (uint32_t i = 0; i < entries; i++) { uint32_t today_energy = (SspmBuffer[41 + (i*2)] << 8) + SspmBuffer[42 + (i*2)]; - if (today_energy != 28702) { // Unknown why sometimes 0x701E (=28702kWh) pops up - total_energy += today_energy; - } + if (28702 == today_energy) { today_energy = 0; } // Unknown why sometimes 0x701E (=28702kWh) pops up + if (0 == i) { energy_today = today_energy; } + if (1 == i) { energy_yesterday = today_energy; } + energy_total += today_energy; } uint32_t channel = SspmBuffer[32]; for (uint32_t module = 0; module < Sspm->module_max; module++) { if ((SspmBuffer[20] == Sspm->module[module][0]) && (SspmBuffer[21] == Sspm->module[module][1])) { - Sspm->total[module][channel] = total_energy; // xkWh + Sspm->energy_today[module][channel] = energy_today; + Sspm->energy_yesterday[module][channel] = energy_yesterday; + Sspm->energy_total[module][channel] = energy_total; // xkWh break; } } @@ -705,6 +720,9 @@ void SSPMHandleReceivedData(void) { Sspm->active_power[module][channel] = (SspmBuffer[37] << 8) + SspmBuffer[38] + (float)SspmBuffer[39] / 100; // x.xxW Sspm->reactive_power[module][channel] = (SspmBuffer[40] << 8) + SspmBuffer[41] + (float)SspmBuffer[42] / 100; // x.xxVAr Sspm->apparent_power[module][channel] = (SspmBuffer[43] << 8) + SspmBuffer[44] + (float)SspmBuffer[45] / 100; // x.xxVA + float power_factor = (Sspm->active_power[module][channel] && Sspm->apparent_power[module][channel]) ? Sspm->active_power[module][channel] / Sspm->apparent_power[module][channel] : 0; + if (power_factor > 1) { power_factor = 1; } + Sspm->power_factor[module][channel] = power_factor; break; } } @@ -1018,15 +1036,19 @@ char* SSPMEnergyFormat(char* result, float* input, uint32_t resolution, bool jso } const char HTTP_SSPM_VOLTAGE[] PROGMEM = - "{s}" D_VOLTAGE " const char HTTP_SSPM_CURRENT[] PROGMEM = "{s}" D_CURRENT " + "{s}" D_POWER_FACTOR "
) - for (uint32_t i = 0; i < 4; i++) { + for (uint32_t i = 1; i < 5; i++) { WSContentSend_P(PSTR("L%d"), relay_base +i); } WSContentSend_P(PSTR("{e}")); // Last column is units ({e} =
%s" D_UNIT_VOLT "{e}"; + "{s}" D_VOLTAGE "%s" D_UNIT_VOLT "{e}"; // {s} =
, {m} = , {e} =
%s" D_UNIT_AMPERE "{e}"; const char HTTP_SSPM_POWER[] PROGMEM = "{s}" D_POWERUSAGE_ACTIVE "%s" D_UNIT_WATT "{e}"; -const char HTTP_SSPM_ENERGY[] PROGMEM = +const char HTTP_SSPM_POWER2[] PROGMEM = "{s}" D_POWERUSAGE_APPARENT "%s" D_UNIT_VA "{e}" "{s}" D_POWERUSAGE_REACTIVE "%s" D_UNIT_VAR "{e}" - "{s}" D_ENERGY_TOTAL "%s" D_UNIT_KILOWATTHOUR "{e}"; // {s} =
, {m} = , {e} =
%s{e}"; +const char HTTP_SSPM_ENERGY[] PROGMEM = + "{s}" D_ENERGY_TODAY "%s" D_UNIT_KILOWATTHOUR "{e}" + "{s}" D_ENERGY_YESTERDAY "%s" D_UNIT_KILOWATTHOUR "{e}" + "{s}" D_ENERGY_TOTAL "%s" D_UNIT_KILOWATTHOUR "{e}"; void SSPMEnergyShow(bool json) { if (!TasmotaGlobal.devices_present) { return; } // Not ready yet @@ -1034,8 +1056,20 @@ void SSPMEnergyShow(bool json) { if (json) { ResponseAppend_P(PSTR(",\"SPM\":{\"" D_JSON_ENERGY "\":[")); for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { - ResponseAppend_P(PSTR("%s%*_f"), (i>0)?",":"", -1, &Sspm->total[i >>2][i &3]); + ResponseAppend_P(PSTR("%s%*_f"), (i>0)?",":"", -1, &Sspm->energy_total[i >>2][i &3]); } +#ifdef SSPM_JSON_ENERGY_YESTERDAY + ResponseAppend_P(PSTR("],\"" D_JSON_YESTERDAY "\":[")); + for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { + ResponseAppend_P(PSTR("%s%*_f"), (i>0)?",":"", -1, &Sspm->energy_today[i >>2][i &3]); + } +#endif +#ifdef SSPM_JSON_ENERGY_TODAY + ResponseAppend_P(PSTR("],\"" D_JSON_TODAY "\":[")); + for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { + ResponseAppend_P(PSTR("%s%*_f"), (i>0)?",":"", -1, &Sspm->energy_yesterday[i >>2][i &3]); + } +#endif ResponseAppend_P(PSTR("],\"" D_JSON_ACTIVE_POWERUSAGE "\":[")); for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { ResponseAppend_P(PSTR("%s%*_f"), (i>0)?",":"", Settings->flag2.wattage_resolution, &Sspm->active_power[i >>2][i &3]); @@ -1048,6 +1082,10 @@ void SSPMEnergyShow(bool json) { for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { ResponseAppend_P(PSTR("%s%*_f"), (i>0)?",":"", Settings->flag2.wattage_resolution, &Sspm->reactive_power[i >>2][i &3]); } + ResponseAppend_P(PSTR("],\"" D_JSON_POWERFACTOR "\":[")); + for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { + ResponseAppend_P(PSTR("%s%*_f"), (i>0)?",":"", 2, &Sspm->power_factor[i >>2][i &3]); + } ResponseAppend_P(PSTR("],\"" D_JSON_VOLTAGE "\":[")); for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { ResponseAppend_P(PSTR("%s%*_f"), (i>0)?",":"", Settings->flag2.voltage_resolution, &Sspm->voltage[i >>2][i &3]); @@ -1075,9 +1113,12 @@ void SSPMEnergyShow(bool json) { WSContentSend_PD(HTTP_SSPM_POWER, SSPMEnergyFormat(value_chr, Sspm->active_power[module], Settings->flag2.wattage_resolution, json)); char valu2_chr[SSPM_SIZE]; char valu3_chr[SSPM_SIZE]; - WSContentSend_PD(HTTP_SSPM_ENERGY, SSPMEnergyFormat(value_chr, Sspm->apparent_power[module], Settings->flag2.wattage_resolution, json), + WSContentSend_PD(HTTP_SSPM_POWER2, SSPMEnergyFormat(value_chr, Sspm->apparent_power[module], Settings->flag2.wattage_resolution, json), SSPMEnergyFormat(valu2_chr, Sspm->reactive_power[module], Settings->flag2.wattage_resolution, json), - SSPMEnergyFormat(valu3_chr, Sspm->total[module], Settings->flag2.energy_resolution, json)); + SSPMEnergyFormat(valu3_chr, Sspm->power_factor[module], 2, json)); + WSContentSend_PD(HTTP_SSPM_ENERGY, SSPMEnergyFormat(value_chr, Sspm->energy_today[module], Settings->flag2.energy_resolution, json), + SSPMEnergyFormat(valu2_chr, Sspm->energy_yesterday[module], Settings->flag2.energy_resolution, json), + SSPMEnergyFormat(valu3_chr, Sspm->energy_total[module], Settings->flag2.energy_resolution, json)); WSContentSend_P(PSTR("
{t}")); // {t} = - Define for next FUNC_WEB_SENSOR } } From a4cb5d98818441b85bff9eeb22b045a3bca0dd60 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Mon, 22 Nov 2021 19:29:53 +0100 Subject: [PATCH 095/185] Berry add metrics to teleperiod --- lib/libesp32/Berry/src/be_debuglib.c | 2 +- lib/libesp32/Berry/src/be_gc.c | 4 ++-- lib/libesp32/Berry/src/be_gc.h | 2 +- lib/libesp32/Berry/src/be_vm.c | 2 +- lib/libesp32/Berry/src/be_vm.h | 2 +- tasmota/support_tasmota.ino | 5 +++++ tasmota/xdrv_52_9_berry.ino | 11 +++++++++++ 7 files changed, 22 insertions(+), 6 deletions(-) diff --git a/lib/libesp32/Berry/src/be_debuglib.c b/lib/libesp32/Berry/src/be_debuglib.c index aa6e8df3a..153af55fb 100644 --- a/lib/libesp32/Berry/src/be_debuglib.c +++ b/lib/libesp32/Berry/src/be_debuglib.c @@ -169,7 +169,7 @@ static int m_counters(bvm *vm) map_insert(vm, "set", vm->counter_set); map_insert(vm, "try", vm->counter_try); map_insert(vm, "raise", vm->counter_exc); - map_insert(vm, "objects", vm->counter_gc_scanned); + map_insert(vm, "objects", vm->counter_gc_kept); be_pop(vm, 1); be_return(vm); } diff --git a/lib/libesp32/Berry/src/be_gc.c b/lib/libesp32/Berry/src/be_gc.c index 8fa560b73..c0bcf0c5a 100644 --- a/lib/libesp32/Berry/src/be_gc.c +++ b/lib/libesp32/Berry/src/be_gc.c @@ -541,7 +541,7 @@ void be_gc_collect(bvm *vm) return; /* the GC cannot run for some reason */ } #if BE_USE_PERF_COUNTERS - vm->counter_gc_scanned = 0; + vm->counter_gc_kept = 0; vm->counter_gc_freed = 0; #endif #if BE_USE_OBSERVABILITY_HOOK @@ -566,6 +566,6 @@ void be_gc_collect(bvm *vm) vm->gc.threshold = next_threshold(vm->gc); #if BE_USE_OBSERVABILITY_HOOK if (vm->obshook != NULL) - (*vm->obshook)(vm, BE_OBS_GC_END, vm->gc.usage, vm->counter_gc_scanned, vm->counter_gc_freed); + (*vm->obshook)(vm, BE_OBS_GC_END, vm->gc.usage, vm->counter_gc_kept, vm->counter_gc_freed); #endif } diff --git a/lib/libesp32/Berry/src/be_gc.h b/lib/libesp32/Berry/src/be_gc.h index acefc3c06..e22903ef9 100644 --- a/lib/libesp32/Berry/src/be_gc.h +++ b/lib/libesp32/Berry/src/be_gc.h @@ -38,7 +38,7 @@ if (!gc_isconst(o)) { \ #define gc_setwhite(o) gc_setmark((o), GC_WHITE) #define gc_setgray(o) gc_setmark((o), GC_GRAY) #if BE_USE_PERF_COUNTERS - #define gc_setdark(o) { vm->counter_gc_scanned++; gc_setmark((o), GC_DARK); } + #define gc_setdark(o) { vm->counter_gc_kept++; gc_setmark((o), GC_DARK); } #else #define gc_setdark(o) gc_setmark((o), GC_DARK) #endif diff --git a/lib/libesp32/Berry/src/be_vm.c b/lib/libesp32/Berry/src/be_vm.c index 6f30835d5..39ae6521e 100644 --- a/lib/libesp32/Berry/src/be_vm.c +++ b/lib/libesp32/Berry/src/be_vm.c @@ -472,7 +472,7 @@ BERRY_API bvm* be_vm_new(void) vm->counter_set = 0; vm->counter_try = 0; vm->counter_exc = 0; - vm->counter_gc_scanned = 0; + vm->counter_gc_kept = 0; vm->counter_gc_freed = 0; #endif return vm; diff --git a/lib/libesp32/Berry/src/be_vm.h b/lib/libesp32/Berry/src/be_vm.h index 0a512210b..4d98c590f 100644 --- a/lib/libesp32/Berry/src/be_vm.h +++ b/lib/libesp32/Berry/src/be_vm.h @@ -112,7 +112,7 @@ struct bvm { uint32_t counter_set; /* counter for SETMBR */ uint32_t counter_try; /* counter for `try` statement */ uint32_t counter_exc; /* counter for raised exceptions */ - uint32_t counter_gc_scanned; /* counter for objects scanned by last gc */ + uint32_t counter_gc_kept; /* counter for objects scanned by last gc */ uint32_t counter_gc_freed; /* counter for objects freed by last gc */ #endif #if BE_USE_DEBUG_HOOK diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index de4a0f360..e23545ca5 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -756,6 +756,11 @@ void MqttShowState(void) ESP_getFreeHeap1024(), GetTextIndexed(stemp1, sizeof(stemp1), Settings->flag3.sleep_normal, kSleepMode), // SetOption60 - Enable normal sleep instead of dynamic sleep TasmotaGlobal.sleep, TasmotaGlobal.loop_load_avg, MqttConnectCount()); +#ifdef USE_BERRY + extern void BrShowState(void); + BrShowState(); +#endif // USE_BERRY + for (uint32_t i = 1; i <= TasmotaGlobal.devices_present; i++) { #ifdef USE_LIGHT if ((LightDevice()) && (i >= LightDevice())) { diff --git a/tasmota/xdrv_52_9_berry.ino b/tasmota/xdrv_52_9_berry.ino index ff74ba950..e938c5bb4 100644 --- a/tasmota/xdrv_52_9_berry.ino +++ b/tasmota/xdrv_52_9_berry.ino @@ -295,6 +295,17 @@ void BerryObservability(bvm *vm, int event...) { va_end(param); } +/*********************************************************************************************\ + * Adde Berry metrics to teleperiod +\*********************************************************************************************/ +void BrShowState(void); +void BrShowState(void) { + // trigger a gc first + be_gc_collect(berry.vm); + ResponseAppend_P(PSTR(",\"Berry\":{\"HeapUsed\":%u,\"Objects\":%u}"), + berry.vm->gc.usage / 1024, berry.vm->counter_gc_kept); +} + /*********************************************************************************************\ * VM Init \*********************************************************************************************/ From 1ea2c2e08da5eed6d2fdac5d803a23f71c0f3db9 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Mon, 22 Nov 2021 19:38:52 +0100 Subject: [PATCH 096/185] Berry fix warning in `tasmota.read_sensors()` --- tasmota/xdrv_52_3_berry_tasmota.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/tasmota/xdrv_52_3_berry_tasmota.ino b/tasmota/xdrv_52_3_berry_tasmota.ino index 438bd69c1..667a8f7b2 100644 --- a/tasmota/xdrv_52_3_berry_tasmota.ino +++ b/tasmota/xdrv_52_3_berry_tasmota.ino @@ -555,6 +555,7 @@ extern "C" { if (top >= 2) { sensor_display = be_tobool(vm, 2); } + be_pop(vm, top); // clear stack to avoid `Error be_top is non zero=1` errors ResponseClear(); if (MqttShowSensor(sensor_display)) { // return string From 95e8d6008197522feaca0836f0213d0abfa7ff16 Mon Sep 17 00:00:00 2001 From: Charles Date: Tue, 23 Nov 2021 17:24:29 +0100 Subject: [PATCH 097/185] use hardware energy counters --- tasmota/xnrg_15_teleinfo.ino | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tasmota/xnrg_15_teleinfo.ino b/tasmota/xnrg_15_teleinfo.ino index dc940d502..37b16084f 100755 --- a/tasmota/xnrg_15_teleinfo.ino +++ b/tasmota/xnrg_15_teleinfo.ino @@ -357,6 +357,7 @@ void DataCallback(struct _ValueList * me, uint8_t flags) Energy.import_active[0] = total/1000.0f; EnergyUpdateTotal(); + AddLog (LOG_LEVEL_INFO, PSTR ("TIC: Total counter updated to %u Wh"), total); } // Wh total index (standard) @@ -568,6 +569,9 @@ void TInfoDrvInit(void) { TasmotaGlobal.energy_driver = XNRG_15; Energy.voltage_available = false; Energy.phase_count = 1; + // init hardware energy counters + Settings->flag3.hardware_energy_total = true; + Settings->energy_kWhtotal = 0; } } From 58b4ee6542b5f5561ca2ed1dd464186327cd2c13 Mon Sep 17 00:00:00 2001 From: Charles Date: Tue, 23 Nov 2021 17:30:36 +0100 Subject: [PATCH 098/185] makes labelCount public --- lib/lib_div/LibTeleinfo/src/LibTeleinfo.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/lib_div/LibTeleinfo/src/LibTeleinfo.h b/lib/lib_div/LibTeleinfo/src/LibTeleinfo.h index 1be54ff5f..3c947b5ca 100644 --- a/lib/lib_div/LibTeleinfo/src/LibTeleinfo.h +++ b/lib/lib_div/LibTeleinfo/src/LibTeleinfo.h @@ -149,6 +149,7 @@ class TInfo uint8_t valuesDump(void); char * valueGet(char * name, char * value); char * valueGet_P(const char * name, char * value); + int labelCount(); boolean listDelete(); unsigned char calcChecksum(char *etiquette, char *valeur, char *horodate=NULL) ; @@ -157,7 +158,6 @@ class TInfo ValueList * valueAdd (char * name, char * value, uint8_t checksum, uint8_t * flags, char * horodate=NULL); boolean valueRemove (char * name); boolean valueRemoveFlagged(uint8_t flags); - int labelCount(); uint32_t horodate2Timestamp( char * pdate) ; void customLabel( char * plabel, char * pvalue, uint8_t * pflags) ; ValueList * checkLine(char * pline) ; From 5315ccb2c485ee960a935c90fc8f3ff1ef31e68a Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Tue, 23 Nov 2021 22:15:08 +0100 Subject: [PATCH 099/185] OTA over HTTPS --- CHANGELOG.md | 1 + .../src/HTTPUpdateLight.cpp | 471 ++++++++++++++++++ .../src/HTTPUpdateLight.h | 140 ++++++ tasmota/support_tasmota.ino | 10 + tasmota/tasmota.ino | 3 + 5 files changed, 625 insertions(+) create mode 100644 lib/libesp32/Berry-HttpClientLight/src/HTTPUpdateLight.cpp create mode 100644 lib/libesp32/Berry-HttpClientLight/src/HTTPUpdateLight.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 28a9eebc2..82bb831ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ All notable changes to this project will be documented in this file. - Preliminary support for Tasmota Apps (.tapp extesions) - Berry support for neopixel (WS2812, SK6812) - Command ``IfxPeriod `` to overrule ``Teleperiod`` for Influx messages (#13750) +- OTA over HTTPS ### Changed - ESP8266 Gratuitous ARP enabled and set to 60 seconds (#13623) diff --git a/lib/libesp32/Berry-HttpClientLight/src/HTTPUpdateLight.cpp b/lib/libesp32/Berry-HttpClientLight/src/HTTPUpdateLight.cpp new file mode 100644 index 000000000..958180e97 --- /dev/null +++ b/lib/libesp32/Berry-HttpClientLight/src/HTTPUpdateLight.cpp @@ -0,0 +1,471 @@ +/** + * + * @file HTTPUpdate.cpp based om ESP8266HTTPUpdate.cpp + * @date 16.10.2018 + * @author Markus Sattler + * + * Copyright (c) 2015 Markus Sattler. All rights reserved. + * This file is part of the ESP32 Http Updater. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "HTTPUpdateLight.h" +#include + +#include +#include // get running partition + +// Tasmota Logging +extern void AddLog(uint32_t loglevel, PGM_P formatP, ...); +enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE}; + +// To do extern "C" uint32_t _SPIFFS_start; +// To do extern "C" uint32_t _SPIFFS_end; + +HTTPUpdateLight::HTTPUpdateLight(void) + : _httpClientTimeout(8000), _ledPin(-1) +{ + _followRedirects = HTTPC_DISABLE_FOLLOW_REDIRECTS; +} + +HTTPUpdateLight::HTTPUpdateLight(int httpClientTimeout) + : _httpClientTimeout(httpClientTimeout), _ledPin(-1) +{ + _followRedirects = HTTPC_DISABLE_FOLLOW_REDIRECTS; +} + +HTTPUpdateLight::~HTTPUpdateLight(void) +{ +} + +// HTTPUpdateResult HTTPUpdateLight::update(WiFiClient& client, const String& url, const String& currentVersion) +// { +// HTTPClient http; +// if(!http.begin(client, url)) +// { +// return HTTP_UPDATE_FAILED; +// } +// return handleUpdate(http, currentVersion, false); +// } + +// HTTPUpdateResult HTTPUpdateLight::updateSpiffs(HTTPClient& httpClient, const String& currentVersion) +// { +// return handleUpdate(httpClient, currentVersion, true); +// } + +// HTTPUpdateResult HTTPUpdateLight::updateSpiffs(WiFiClient& client, const String& url, const String& currentVersion) +// { +// HTTPClient http; +// if(!http.begin(client, url)) +// { +// return HTTP_UPDATE_FAILED; +// } +// return handleUpdate(http, currentVersion, true); +// } + +HTTPUpdateResult HTTPUpdateLight::update(HTTPClientLight& httpClient, + const String& currentVersion) +{ + return handleUpdate(httpClient, currentVersion, false); +} + +// HTTPUpdateResult HTTPUpdateLight::update(WiFiClient& client, const String& host, uint16_t port, const String& uri, +// const String& currentVersion) +// { +// HTTPClient http; +// if(!http.begin(client, host, port, uri)) +// { +// return HTTP_UPDATE_FAILED; +// } +// return handleUpdate(http, currentVersion, false); +// } + +/** + * return error code as int + * @return int error code + */ +int HTTPUpdateLight::getLastError(void) +{ + return _lastError; +} + +/** + * return error code as String + * @return String error + */ +String HTTPUpdateLight::getLastErrorString(void) +{ + + if(_lastError == 0) { + return String(); // no error + } + + // error from Update class + if(_lastError > 0) { + StreamString error; + Update.printError(error); + error.trim(); // remove line ending + return String("Update error: ") + error; + } + + // error from http client + if(_lastError > -100) { + return String("HTTP error: ") + HTTPClientLight::errorToString(_lastError); + } + + switch(_lastError) { + case HTTP_UE_TOO_LESS_SPACE: + return "Not Enough space"; + case HTTP_UE_SERVER_NOT_REPORT_SIZE: + return "Server Did Not Report Size"; + case HTTP_UE_SERVER_FILE_NOT_FOUND: + return "File Not Found (404)"; + case HTTP_UE_SERVER_FORBIDDEN: + return "Forbidden (403)"; + case HTTP_UE_SERVER_WRONG_HTTP_CODE: + return "Wrong HTTP Code"; + case HTTP_UE_SERVER_FAULTY_MD5: + return "Wrong MD5"; + case HTTP_UE_BIN_VERIFY_HEADER_FAILED: + return "Verify Bin Header Failed"; + case HTTP_UE_BIN_FOR_WRONG_FLASH: + return "New Binary Does Not Fit Flash Size"; + case HTTP_UE_NO_PARTITION: + return "Partition Could Not be Found"; + } + + return String(); +} + +extern String getSketchSHA256(); +// String getSketchSHA256() { +// const size_t HASH_LEN = 32; // SHA-256 digest length + +// uint8_t sha_256[HASH_LEN] = { 0 }; + +// // get sha256 digest for running partition +// if(esp_partition_get_sha256(esp_ota_get_running_partition(), sha_256) == 0) { +// char buffer[2 * HASH_LEN + 1]; + +// for(size_t index = 0; index < HASH_LEN; index++) { +// uint8_t nibble = (sha_256[index] & 0xf0) >> 4; +// buffer[2 * index] = nibble < 10 ? char(nibble + '0') : char(nibble - 10 + 'A'); + +// nibble = sha_256[index] & 0x0f; +// buffer[2 * index + 1] = nibble < 10 ? char(nibble + '0') : char(nibble - 10 + 'A'); +// } + +// buffer[2 * HASH_LEN] = '\0'; + +// return String(buffer); +// } else { + +// return String(); +// } +// } + +/** + * + * @param http HTTPClientLight * + * @param currentVersion const char * + * @return HTTPUpdateResult + */ +HTTPUpdateResult HTTPUpdateLight::handleUpdate(HTTPClientLight& http, const String& currentVersion, bool spiffs) +{ + + HTTPUpdateResult ret = HTTP_UPDATE_FAILED; + + // use HTTP/1.0 for update since the update handler not support any transfer Encoding + http.useHTTP10(true); + http.setTimeout(_httpClientTimeout); + http.setFollowRedirects(_followRedirects); + http.setUserAgent("ESP32-http-Update"); + http.addHeader("Cache-Control", "no-cache"); + http.addHeader("x-ESP32-STA-MAC", WiFi.macAddress()); + http.addHeader("x-ESP32-AP-MAC", WiFi.softAPmacAddress()); + http.addHeader("x-ESP32-free-space", String(ESP.getFreeSketchSpace())); + http.addHeader("x-ESP32-sketch-size", String(ESP.getSketchSize())); + String sketchMD5 = ESP.getSketchMD5(); + if(sketchMD5.length() != 0) { + http.addHeader("x-ESP32-sketch-md5", sketchMD5); + } + // Add also a SHA256 + String sketchSHA256 = getSketchSHA256(); + if(sketchSHA256.length() != 0) { + http.addHeader("x-ESP32-sketch-sha256", sketchSHA256); + } + http.addHeader("x-ESP32-chip-size", String(ESP.getFlashChipSize())); + http.addHeader("x-ESP32-sdk-version", ESP.getSdkVersion()); + + if(spiffs) { + http.addHeader("x-ESP32-mode", "spiffs"); + } else { + http.addHeader("x-ESP32-mode", "sketch"); + } + + if(currentVersion && currentVersion[0] != 0x00) { + http.addHeader("x-ESP32-version", currentVersion); + } + + const char * headerkeys[] = { "x-MD5" }; + size_t headerkeyssize = sizeof(headerkeys) / sizeof(char*); + + // track these headers + http.collectHeaders(headerkeys, headerkeyssize); + + uint32_t http_connect_time = millis(); + + int code = http.GET(); + int len = http.getSize(); + + // Add specific logging for Tasmota + if (len < 0) { + if (len <= -1000) { + AddLog(LOG_LEVEL_INFO, "OTA: TLS connection error %d after %d ms", -len - 1000, millis() - http_connect_time); + } else if (len == -1) { + AddLog(LOG_LEVEL_INFO, "OTA: Connection timeout after %d ms", len, millis() - http_connect_time); + } else { + AddLog(LOG_LEVEL_INFO, "OTA: Connection error %d after %d ms", len, millis() - http_connect_time); + } + } else { + AddLog(LOG_LEVEL_DEBUG, PSTR("OTA: Connected in %d ms, stack low mark %d"), + millis() - http_connect_time, uxTaskGetStackHighWaterMark(nullptr)); + } + + if(code <= 0) { + // log_e("HTTP error: %s\n", http.errorToString(code).c_str()); + _lastError = code; + http.end(); + return HTTP_UPDATE_FAILED; + } + + + log_d("Header read fin.\n"); + log_d("Server header:\n"); + log_d(" - code: %d\n", code); + log_d(" - len: %d\n", len); + + if(http.hasHeader("x-MD5")) { + log_d(" - MD5: %s\n", http.header("x-MD5").c_str()); + } + + log_d("ESP32 info:\n"); + log_d(" - free Space: %d\n", ESP.getFreeSketchSpace()); + log_d(" - current Sketch Size: %d\n", ESP.getSketchSize()); + + if(currentVersion && currentVersion[0] != 0x00) { + log_d(" - current version: %s\n", currentVersion.c_str() ); + } + + switch(code) { + case HTTP_CODE_OK: ///< OK (Start Update) + if(len > 0) { + bool startUpdate = true; + if(spiffs) { + const esp_partition_t* _partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS, NULL); + if(!_partition){ + _lastError = HTTP_UE_NO_PARTITION; + return HTTP_UPDATE_FAILED; + } + + if(len > _partition->size) { + log_e("spiffsSize to low (%d) needed: %d\n", _partition->size, len); + startUpdate = false; + } + } else { + int sketchFreeSpace = ESP.getFreeSketchSpace(); + if(!sketchFreeSpace){ + _lastError = HTTP_UE_NO_PARTITION; + return HTTP_UPDATE_FAILED; + } + + if(len > sketchFreeSpace) { + log_e("FreeSketchSpace to low (%d) needed: %d\n", sketchFreeSpace, len); + startUpdate = false; + } + } + + if(!startUpdate) { + _lastError = HTTP_UE_TOO_LESS_SPACE; + ret = HTTP_UPDATE_FAILED; + } else { + // Warn main app we're starting up... + if (_cbStart) { + _cbStart(); + } + + WiFiClient * tcp = http.getStreamPtr(); + +// To do? WiFiUDP::stopAll(); +// To do? WiFiClient::stopAllExcept(tcp); + + delay(100); + + int command; + + if(spiffs) { + command = U_SPIFFS; + log_d("runUpdate spiffs...\n"); + } else { + command = U_FLASH; + log_d("runUpdate flash...\n"); + } + + if(!spiffs) { +/* To do + uint8_t buf[4]; + if(tcp->peekBytes(&buf[0], 4) != 4) { + log_e("peekBytes magic header failed\n"); + _lastError = HTTP_UE_BIN_VERIFY_HEADER_FAILED; + http.end(); + return HTTP_UPDATE_FAILED; + } +*/ + + // check for valid first magic byte +// if(buf[0] != 0xE9) { + if(tcp->peek() != 0xE9) { + log_e("Magic header does not start with 0xE9\n"); + _lastError = HTTP_UE_BIN_VERIFY_HEADER_FAILED; + http.end(); + return HTTP_UPDATE_FAILED; + + } +/* To do + uint32_t bin_flash_size = ESP.magicFlashChipSize((buf[3] & 0xf0) >> 4); + + // check if new bin fits to SPI flash + if(bin_flash_size > ESP.getFlashChipRealSize()) { + log_e("New binary does not fit SPI Flash size\n"); + _lastError = HTTP_UE_BIN_FOR_WRONG_FLASH; + http.end(); + return HTTP_UPDATE_FAILED; + } +*/ + } + if(runUpdate(*tcp, len, http.header("x-MD5"), command)) { + ret = HTTP_UPDATE_OK; + log_d("Update ok\n"); + http.end(); + // Warn main app we're all done + if (_cbEnd) { + _cbEnd(); + } + + if(_rebootOnUpdate && !spiffs) { + ESP.restart(); + } + + } else { + ret = HTTP_UPDATE_FAILED; + log_e("Update failed\n"); + } + } + } else { + _lastError = HTTP_UE_SERVER_NOT_REPORT_SIZE; + ret = HTTP_UPDATE_FAILED; + log_e("Content-Length was 0 or wasn't set by Server?!\n"); + } + break; + case HTTP_CODE_NOT_MODIFIED: + ///< Not Modified (No updates) + ret = HTTP_UPDATE_NO_UPDATES; + break; + case HTTP_CODE_NOT_FOUND: + _lastError = HTTP_UE_SERVER_FILE_NOT_FOUND; + ret = HTTP_UPDATE_FAILED; + break; + case HTTP_CODE_FORBIDDEN: + _lastError = HTTP_UE_SERVER_FORBIDDEN; + ret = HTTP_UPDATE_FAILED; + break; + default: + _lastError = HTTP_UE_SERVER_WRONG_HTTP_CODE; + ret = HTTP_UPDATE_FAILED; + AddLog(LOG_LEVEL_INFO, "OTA: unsupported HTTP return code %i", code); + // log_e("HTTP Code is (%d)\n", code); + break; + } + + http.end(); + return ret; +} + +/** + * write Update to flash + * @param in Stream& + * @param size uint32_t + * @param md5 String + * @return true if Update ok + */ +bool HTTPUpdateLight::runUpdate(Stream& in, uint32_t size, String md5, int command) +{ + + StreamString error; + + if (_cbProgress) { + Update.onProgress(_cbProgress); + } + + if(!Update.begin(size, command, _ledPin, _ledOn)) { + _lastError = Update.getError(); + Update.printError(error); + error.trim(); // remove line ending + log_e("Update.begin failed! (%s)\n", error.c_str()); + return false; + } + + if (_cbProgress) { + _cbProgress(0, size); + } + + if(md5.length()) { + if(!Update.setMD5(md5.c_str())) { + _lastError = HTTP_UE_SERVER_FAULTY_MD5; + log_e("Update.setMD5 failed! (%s)\n", md5.c_str()); + return false; + } + } + +// To do: the SHA256 could be checked if the server sends it + + if(Update.writeStream(in) != size) { + _lastError = Update.getError(); + Update.printError(error); + error.trim(); // remove line ending + log_e("Update.writeStream failed! (%s)\n", error.c_str()); + return false; + } + + if (_cbProgress) { + _cbProgress(size, size); + } + + if(!Update.end()) { + _lastError = Update.getError(); + Update.printError(error); + error.trim(); // remove line ending + log_e("Update.end failed! (%s)\n", error.c_str()); + return false; + } + + return true; +} + +#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_HTTPUPDATE) +HTTPUpdateLight httpUpdateLight; +#endif diff --git a/lib/libesp32/Berry-HttpClientLight/src/HTTPUpdateLight.h b/lib/libesp32/Berry-HttpClientLight/src/HTTPUpdateLight.h new file mode 100644 index 000000000..cbed38bd6 --- /dev/null +++ b/lib/libesp32/Berry-HttpClientLight/src/HTTPUpdateLight.h @@ -0,0 +1,140 @@ +/** + * + * @file HTTPUpdate.h based on ESP8266HTTPUpdate.h + * @date 16.10.2018 + * @author Markus Sattler + * + * Copyright (c) 2015 Markus Sattler. All rights reserved. + * This file is part of the ESP32 Http Updater. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef ___HTTP_UPDATE_LIGHT_H___ +#define ___HTTP_UPDATE_LIGHT_H___ + +#include +#include +#include +#include +#include +#include +#include + +/// note we use HTTP client errors too so we start at 100 +// #define HTTP_UE_TOO_LESS_SPACE (-100) +// #define HTTP_UE_SERVER_NOT_REPORT_SIZE (-101) +// #define HTTP_UE_SERVER_FILE_NOT_FOUND (-102) +// #define HTTP_UE_SERVER_FORBIDDEN (-103) +// #define HTTP_UE_SERVER_WRONG_HTTP_CODE (-104) +// #define HTTP_UE_SERVER_FAULTY_MD5 (-105) +// #define HTTP_UE_BIN_VERIFY_HEADER_FAILED (-106) +// #define HTTP_UE_BIN_FOR_WRONG_FLASH (-107) +// #define HTTP_UE_NO_PARTITION (-108) + +// enum HTTPUpdateResult { +// HTTP_UPDATE_FAILED, +// HTTP_UPDATE_NO_UPDATES, +// HTTP_UPDATE_OK +// }; + +// typedef HTTPUpdateResult t_httpUpdate_return; // backward compatibility + +// using HTTPUpdateStartCB = std::function; +// using HTTPUpdateEndCB = std::function; +// using HTTPUpdateErrorCB = std::function; +// using HTTPUpdateProgressCB = std::function; + +class HTTPUpdateLight +{ +public: + HTTPUpdateLight(void); + HTTPUpdateLight(int httpClientTimeout); + ~HTTPUpdateLight(void); + + void rebootOnUpdate(bool reboot) + { + _rebootOnUpdate = reboot; + } + + /** + * set redirect follow mode. See `followRedirects_t` enum for avaliable modes. + * @param follow + */ + void setFollowRedirects(followRedirects_t follow) + { + _followRedirects = follow; + } + + void setLedPin(int ledPin = -1, uint8_t ledOn = HIGH) + { + _ledPin = ledPin; + _ledOn = ledOn; + } + + // t_httpUpdate_return update(WiFiClient& client, const String& url, const String& currentVersion = ""); + + // t_httpUpdate_return update(WiFiClient& client, const String& host, uint16_t port, const String& uri = "/", + // const String& currentVersion = ""); + + // t_httpUpdate_return updateSpiffs(WiFiClient& client, const String& url, const String& currentVersion = ""); + + t_httpUpdate_return update(HTTPClientLight& httpClient, + const String& currentVersion = ""); + + // t_httpUpdate_return updateSpiffs(HTTPClient &httpClient, const String ¤tVersion = ""); + + // Notification callbacks + void onStart(HTTPUpdateStartCB cbOnStart) { _cbStart = cbOnStart; } + void onEnd(HTTPUpdateEndCB cbOnEnd) { _cbEnd = cbOnEnd; } + void onError(HTTPUpdateErrorCB cbOnError) { _cbError = cbOnError; } + void onProgress(HTTPUpdateProgressCB cbOnProgress) { _cbProgress = cbOnProgress; } + + int getLastError(void); + String getLastErrorString(void); + +protected: + t_httpUpdate_return handleUpdate(HTTPClientLight& http, const String& currentVersion, bool spiffs = false); + bool runUpdate(Stream& in, uint32_t size, String md5, int command = U_FLASH); + + // Set the error and potentially use a CB to notify the application + void _setLastError(int err) { + _lastError = err; + if (_cbError) { + _cbError(err); + } + } + int _lastError; + bool _rebootOnUpdate = true; +private: + int _httpClientTimeout; + followRedirects_t _followRedirects; + + // Callbacks + HTTPUpdateStartCB _cbStart; + HTTPUpdateEndCB _cbEnd; + HTTPUpdateErrorCB _cbError; + HTTPUpdateProgressCB _cbProgress; + + int _ledPin; + uint8_t _ledOn; +}; + +#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_HTTPUPDATE) +extern HTTPUpdateLight httpUpdateLight; +#endif + +#endif /* ___HTTP_UPDATE_LIGHT_H___ */ diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index e23545ca5..13671b18f 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -1213,8 +1213,18 @@ void Every250mSeconds(void) char version[50]; snprintf_P(version, sizeof(version), PSTR("%s%s"), TasmotaGlobal.version, TasmotaGlobal.image_name); AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPLOAD "%s %s"), full_ota_url, version); +#if defined(ESP32) && defined(USE_WEBCLIENT_HTTPS) + HTTPClientLight OTAclient; + if (!OTAclient.begin(full_ota_url)) { + AddLog(LOG_LEVEL_INFO, "OTA: unsupported protocol"); + ota_result = -999; + } else { + ota_result = (HTTP_UPDATE_FAILED != httpUpdateLight.update(OTAclient, version)); + } +#else // standard OTA over HTTP WiFiClient OTAclient; ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(OTAclient, full_ota_url, version)); +#endif if (!ota_result) { #ifndef FIRMWARE_MINIMAL int ota_error = ESPhttpUpdate.getLastError(); diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index f4008b93d..3e1ed63c4 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -35,6 +35,9 @@ // Libraries #include // Ota #include // Ota +#ifdef ESP32 + #include "HTTPUpdateLight.h" // Ota over HTTPS for ESP32 +#endif #include // Webserver, Updater #include #include From 95c94ff4f348394bf1a8b9b270682478a0a827f9 Mon Sep 17 00:00:00 2001 From: stefanbode Date: Wed, 24 Nov 2021 09:34:51 +0100 Subject: [PATCH 100/185] Small bugfix Wallbuttons did not work after first use because shutter was in tilt mode. up/down webbuttons did not stop the shutter correctly in tilt mode --- tasmota/xdrv_27_shutter.ino | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index f7ddfb222..b106f37fd 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -558,6 +558,8 @@ void ShutterUpdatePosition(void) //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Pre: Tilt not match %d -> %d, moving: %d"),Shutter[i].tilt_real_pos,Shutter[i].tilt_target_pos,Shutter[i].tiltmoving); if (abs(Shutter[i].tilt_real_pos - Shutter[i].tilt_target_pos) > Shutter[i].min_TiltChange && Shutter[i].tiltmoving == 0) { AddLog(LOG_LEVEL_INFO, PSTR("SHT: Tilt not match %d -> %d"),Shutter[i].tilt_real_pos,Shutter[i].tilt_target_pos); + char databuf[1] = ""; + XdrvMailbox.data = databuf; XdrvMailbox.payload = -99; XdrvMailbox.index = i+1; Shutter[i].tiltmoving = 1; @@ -718,6 +720,9 @@ void ShutterRelayChanged(void) } switch (ShutterGlobal.position_mode) { // enum Shutterposition_mode {SHT_TIME, SHT_TIME_UP_DOWN, SHT_TIME_GARAGE, SHT_COUNTER, SHT_PWM_VALUE, SHT_PWM_TIME,}; + if (powerstate_local > 0) { + Shutter[i].tiltmoving = 0; + } case SHT_TIME_UP_DOWN: case SHT_COUNTER: case SHT_PWM_VALUE: From daba522c9338071ffeb785b08e44a0afd1fdff58 Mon Sep 17 00:00:00 2001 From: stefanbode Date: Wed, 24 Nov 2021 17:43:25 +0100 Subject: [PATCH 101/185] fix of the fix... --- tasmota/xdrv_27_shutter.ino | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index b106f37fd..23940ce79 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -718,11 +718,11 @@ void ShutterRelayChanged(void) TasmotaGlobal.last_source = SRC_SHUTTER; // avoid switch off in the next loop if (Shutter[i].direction != 0 ) Shutter[i].target_position = Shutter[i].real_position; } + if (powerstate_local > 0) { + Shutter[i].tiltmoving = 0; + } switch (ShutterGlobal.position_mode) { // enum Shutterposition_mode {SHT_TIME, SHT_TIME_UP_DOWN, SHT_TIME_GARAGE, SHT_COUNTER, SHT_PWM_VALUE, SHT_PWM_TIME,}; - if (powerstate_local > 0) { - Shutter[i].tiltmoving = 0; - } case SHT_TIME_UP_DOWN: case SHT_COUNTER: case SHT_PWM_VALUE: @@ -766,7 +766,7 @@ void ShutterRelayChanged(void) } // switch (ShutterGlobal.position_mode) - AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d, Target %ld, Powerstatelocal %d"), i+1, Shutter[i].target_position, powerstate_local); + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d, Target %ld, Power: %d, tiltmv: %d"), i+1, Shutter[i].target_position, powerstate_local,Shutter[i].tiltmoving); } // if (manual_relays_changed) } // for (uint32_t i = 0; i < TasmotaGlobal.shutters_present; i++) } From b481a421e17da01db7b762516ec79b26e3cfb1d4 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Thu, 25 Nov 2021 07:04:41 +0100 Subject: [PATCH 102/185] some serial tweeks --- tasmota/xdrv_10_scripter.ino | 58 +++++++++++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index 48fe3e891..d5a2c5bdb 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -2595,6 +2595,23 @@ chknext: #endif break; case 'i': + if (!strncmp(vname, "ins(", 4)) { + char s1[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp + 4, OPER_EQU, s1, 0); + SCRIPT_SKIP_SPACES + char s2[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, s2, 0); + SCRIPT_SKIP_SPACES + char *cp = strstr(s1, s2); + if (cp) { + fvar = ((uint32_t)cp - (uint32_t)s1); + } else { + fvar = -1; + } + lp++; + len = 0; + goto exit; + } if (!strncmp(vname, "int(", 4)) { lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, gv); fvar = floor(fvar); @@ -3206,6 +3223,12 @@ chknext: uint8_t stopb = (*lp++ & 0x3) - 1; sconfig = (bits - 5) + (parity * 8) + stopb * 4; } + SCRIPT_SKIP_SPACES + // check for rec buffer + float rxbsiz = 128; + if (*lp!=')') { + lp = GetNumericArgument(lp, OPER_EQU, &rxbsiz, gv); + } fvar= -1; if (glob_script_mem.sp) { fvar == -1; @@ -3214,7 +3237,8 @@ chknext: AddLog(LOG_LEVEL_INFO, PSTR("warning: pins already used")); } - glob_script_mem.sp = new TasmotaSerial(rxpin, txpin, 1); + glob_script_mem.sp = new TasmotaSerial(rxpin, txpin, 1, 0, rxbsiz); + if (glob_script_mem.sp) { uint32_t config; #ifdef ESP8266 @@ -3226,8 +3250,10 @@ chknext: #endif // ESP32 fvar = glob_script_mem.sp->begin(br, config); uint32_t savc = Settings->serial_config; + //setRxBufferSize(TMSBSIZ); + Settings->serial_config = sconfig; - AddLog(LOG_LEVEL_INFO, PSTR("Serial port set to %s %d bit/s at rx=%d tx=%d"), GetSerialConfig().c_str(), (uint32_t)br, (uint32_t)rxpin, (uint32_t)txpin); + AddLog(LOG_LEVEL_INFO, PSTR("Serial port set to %s %d bit/s at rx=%d tx=%d rbu=%d"), GetSerialConfig().c_str(), (uint32_t)br, (uint32_t)rxpin, (uint32_t)txpin, (uint32_t)rxbsiz); Settings->serial_config = savc; if (rxpin == 3 and txpin == 1) ClaimSerial(); @@ -3295,21 +3321,37 @@ chknext: len = 0; goto exit; } - if (!strncmp(vname, "sr(", 4)) { - char str[SCRIPT_MAXSSIZE]; - memset(str, 0, sizeof(str)); + if (!strncmp(vname, "sr(", 3)) { + uint16_t size = glob_script_mem.max_ssize; + char str[size]; + memset(str, 0, size); + lp += 3; + uint8_t runt = 0; + if (*lp != ')') { + // read until + lp = GetNumericArgument(lp, OPER_EQU, &fvar, 0); + runt = fvar; + } fvar = -1; + uint8_t flg = 0; if (glob_script_mem.sp) { - for (uint8_t index = 0; index < sizeof(str) - 1; index++) { + for (uint16_t index = 0; index < (size - 1); index++) { if (!glob_script_mem.sp->available()) { + flg = 1; break; } - str[index] = glob_script_mem.sp->read(); + uint8_t iob = glob_script_mem.sp->read(); + if (iob == runt) { + flg = 2; + break; + } + str[index] = iob; } } + //AddLog(LOG_LEVEL_INFO, PSTR(">>: %d - %d - %d - %s"), runt, flg, index, str); lp++; len = 0; - if (sp) strlcpy(sp, str, glob_script_mem.max_ssize); + if (sp) strlcpy(sp, str, size); goto strexit;; } if (!strncmp(vname, "sc(", 3)) { From b56ff4dfa352cd826c000e3f0c399b188f1ac3dc Mon Sep 17 00:00:00 2001 From: stefanbode Date: Thu, 25 Nov 2021 08:31:40 +0100 Subject: [PATCH 103/185] Allow tilt change with wall buttons If venetian shutter is stopped before start moving the actual tilt is stored as new target tilt for further operations. --- tasmota/xdrv_27_shutter.ino | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 23940ce79..ea98aa625 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -479,6 +479,10 @@ void ShutterPowerOff(uint8_t i) if (Shutter[i].direction !=0) { Shutter[i].direction = 0; } + if (Shutter[i].real_position == Shutter[i].start_position) { + //AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Update target tilt shutter %d from %d to %d"), i+1, Shutter[i].tilt_target_pos , Shutter[i].tilt_real_pos); + Shutter[i].tilt_target_pos = Shutter[i].tilt_real_pos; + } TasmotaGlobal.rules_flag.shutter_moved = 1; switch (Shutter[i].switch_mode) { case SHT_SWITCH: From 4f67e0cdb8fc764277783dc6fe93593616e5cd20 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 25 Nov 2021 10:27:20 +0100 Subject: [PATCH 104/185] Add more comments --- tasmota/xdrv_86_esp32_sonoff_spm.ino | 56 ++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/tasmota/xdrv_86_esp32_sonoff_spm.ino b/tasmota/xdrv_86_esp32_sonoff_spm.ino index e26c214c6..99df60cfb 100644 --- a/tasmota/xdrv_86_esp32_sonoff_spm.ino +++ b/tasmota/xdrv_86_esp32_sonoff_spm.ino @@ -109,6 +109,7 @@ #define SSPM_FUNC_SET_SCHEME 10 // 0x0A #define SSPM_FUNC_GET_SCHEME 11 // 0x0B #define SSPM_FUNC_SET_TIME 12 // 0x0C +#define SSPM_FUNC_IAMHERE 13 // 0x0D #define SSPM_FUNC_INIT_SCAN 16 // 0x10 #define SSPM_FUNC_UNITS 21 // 0x15 #define SSPM_FUNC_GET_ENERGY_TOTAL 22 // 0x16 @@ -371,7 +372,10 @@ void SSPMSendSetTime(void) { /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 0c 00 0b 07 e5 0b 06 0c 39 01 00 00 02 00 04 8a 37 - Marker |Module id |Ac|Cm|Size |YY YY MM DD HH MM SS|Ln|St|Tr| |Ix|Chksm| + Marker |Module id |Ac|Cm|Size |YY YY MM DD HH MM SS|Ln|St|Tr |Ix|Chksm| + UTC time + Tr = Time zone, [-12,+14], can be a decimal, such as 7.5 + */ SSPMInitSend(); SspmBuffer[16] = SSPM_FUNC_SET_TIME; @@ -387,6 +391,20 @@ void SSPMSendSetTime(void) { SSPMSend(33); } +void SSPMSendIAmHere(uint32_t module) { + /* + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 + AA 55 01 8b 34 32 37 39 37 34 13 4b 35 36 37 00 0d 00 00 17 35 b6 + Marker |Module id |Ac|Cm|Size |Ix|Chksm| + + Response + AA 55 01 8b 34 32 37 39 37 34 13 4b 35 36 37 80 0d 00 01 00 17 48 b5 + Marker |Module id |Ac|Cm|Size |Rs|Ix|Chksm| + */ + + +} + void SSPMSendSetRelay(uint32_t relay, uint32_t state) { /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @@ -680,6 +698,36 @@ void SSPMHandleReceivedData(void) { } Sspm->allow_updates = 1; } + break; + case SSPM_FUNC_GET_LOG: + /* 0x1A + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 80 1a 01 3a 00 6b 7e 32 37 39 37 34 13 4b 35 36 37 + 1e Number of log entries (1e = 30) + 07 e5 0b 06 0f 25 19 02 01 00 10 byte log entry + |-- trigger 00 = App, 01 = Device, 02 = Overload, 03 = Overtemp + |----- state 00 = Off, 01 = On + |-------- Channel 00 to 03 + |----------- Second = 25 + |-------------- Minute = 37 + |----------------- Hour = 15 + |-------------------- Day = 6 + |----------------------- Month = 11 = November + ----------------------------- Year 07 e5 = 2021 + 07 e5 0b 06 0f 1f 08 00 00 01 + 07 e5 0b 06 0f 1f 04 02 00 01 + 07 e5 0b 06 0f 1e 32 01 00 01 + 07 e5 0b 06 0f 1e 1e 01 01 01 + 07 e5 0b 06 0f 18 38 02 01 01 + 07 e5 0b 06 0f 12 38 00 01 01 + 07 e5 0b 06 0e 37 36 03 00 00 + 07 e5 0b 06 0e 37 36 01 00 00 + 07 e5 0b 06 0e 37 1e 03 01 00 + 07 e5 0b 06 0e 36 37 01 01 00 + ... + 07 e5 0b 06 0d 30 2d 03 00 01 09 89 fe + */ + break; case SSPM_FUNC_ENERGY_PERIOD: /* 0x1B @@ -703,9 +751,10 @@ void SSPMHandleReceivedData(void) { AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 06 00 1C 8B 34 32 37 39 37 34 13 4B 35 36 37 08 02 04 00 DC 14 01 C1 3D 00 10 19 01 C2 29 4B 37 6B 26 AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 06 00 1c 8b 34 32 37 39 37 34 13 4b 35 36 37 08 00 44 00 e1 35 00 9a 3e 00 01 45 00 9a 38 00 08 8b ae AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 06 00 1c 8b 34 32 37 39 37 34 13 4b 35 36 37 08 00 4a 00 e1 22 00 61 4d 00 2c 38 00 a8 28 20 26 21 70 - |Ch|Curre|Voltage |ActivePo|Reactive|Apparent|??| + |Ch|Curre|Voltage |ActivePo|Reactive|Apparent|5m| Values are XX XX - number XX - decimals + 5m - 5 minutes Power Consumption (Ws) */ { uint32_t channel = 0; @@ -768,8 +817,9 @@ void SSPMHandleReceivedData(void) { 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 13 00 24 6b 7e 32 37 39 37 34 13 4b 35 36 37 04 00 00 00 82 01 00 00 14 00 00 0a 00 f0 00 00 00 0a 11 30 00 00 00 0a 02 8f cd AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 13 00 24 8b 34 32 37 39 37 34 13 4b 35 36 37 04 00 00 00 82 01 00 00 14 00 00 0a 00 f0 00 00 00 0a 11 30 00 00 00 0a 02 a0 6f - Marker | |Ac|Cm|Size |Module id |Ch| |Max I|Min I|Max U |Min U |Max P |Min P |Ix|Chksm| + Marker | |Ac|Cm|Size |Module id |Ch| |Ty| |Max I|Min I|Max U |Min U |Max P |Min P |Ix|Chksm| | 20A| 0.1A| 240V| 0.1V| 4400W| 0.1W| + Ty = Type of sub-device. 130: Four-channel sub-device */ if ((0x24 == Sspm->expected_bytes) && (Sspm->module_max < SSPM_MAX_MODULES)) { memcpy(Sspm->module[1], Sspm->module[0], (SSPM_MAX_MODULES -1) * SSPM_MODULE_NAME_SIZE); From f020cac8eccf31135c51c394097dabcf7fe57833 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 25 Nov 2021 15:00:33 +0100 Subject: [PATCH 105/185] Update Tasmota_build_devel.yml --- .github/workflows/Tasmota_build_devel.yml | 38 ++++++++++++----------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/.github/workflows/Tasmota_build_devel.yml b/.github/workflows/Tasmota_build_devel.yml index e7c98decd..96e63247e 100644 --- a/.github/workflows/Tasmota_build_devel.yml +++ b/.github/workflows/Tasmota_build_devel.yml @@ -1,9 +1,9 @@ -name: Build_firmware_devel +name: Build_firmware_development on: workflow_dispatch: # Manually start a workflow push: - branches: test # Dummy branch run only manually for testing! +# branches: development paths-ignore: - '.github/**' # Ignore changes towards the .github directory - '**.md' # Do no build if *.md files changes @@ -1324,7 +1324,6 @@ jobs: runs-on: ubuntu-latest continue-on-error: true steps: - - uses: actions/checkout@v2 - uses: actions/download-artifact@v2 with: name: firmware @@ -1361,30 +1360,33 @@ jobs: [ ! -f ./mv_firmware/firmware/* ] || mv ./mv_firmware/firmware/* ./firmware/tasmota/languages/ - name: Display files to transfer run: ls -R ./* + - name: Push Firmware files to tmp repo + uses: Jason2866/copy_file_to_another_repo_action@main + env: + API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }} + with: + source_file: 'firmware' + destination_repo: 'arendst/tmp_copy' + destination_branch: 'firmware' + user_email: 'github-actions@github.com' + user_name: 'github-actions' - - name: Push Firmware files to https://github.com/arendst/Tasmota-firmware - run: | - git config user.name "Platformio BUILD" - git config user.email github-actions@github.com - git switch -c work - git remote add -f Tasmota "https://github.com/arendst/Tasmota-firmware.git" --track main - git rm -r --cached . - git add -f ./firmware/* - git commit -m ${GITHUB_SHA} - git merge Tasmota-firmware/main --allow-unrelated-histories - git push -u origin main - + Start_final_copy: + needs: Upload + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 - name: Creat trigger.txt run: | echo ${GITHUB_SHA} &> trigger.txt echo "$( Date: Thu, 25 Nov 2021 15:15:56 +0100 Subject: [PATCH 106/185] Update Tasmota_build_devel.yml --- .github/workflows/Tasmota_build_devel.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/Tasmota_build_devel.yml b/.github/workflows/Tasmota_build_devel.yml index 96e63247e..dba5b61da 100644 --- a/.github/workflows/Tasmota_build_devel.yml +++ b/.github/workflows/Tasmota_build_devel.yml @@ -3,7 +3,7 @@ name: Build_firmware_development on: workflow_dispatch: # Manually start a workflow push: -# branches: development + branches: development paths-ignore: - '.github/**' # Ignore changes towards the .github directory - '**.md' # Do no build if *.md files changes @@ -1386,7 +1386,7 @@ jobs: API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }} with: source_file: 'trigger.txt' - destination_repo: 'Jason2866/tmp_copy' - destination_branch: 'action' + destination_repo: 'arendst/tmp_copy' + destination_branch: 'action-development' user_email: 'github-actions@github.com' user_name: 'github-actions' From 7edcf6fe7a94d236da8e12482598970aae903dc6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 25 Nov 2021 15:18:24 +0100 Subject: [PATCH 107/185] Disable for now --- .github/workflows/Tasmota_build_devel.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Tasmota_build_devel.yml b/.github/workflows/Tasmota_build_devel.yml index dba5b61da..83788c8c8 100644 --- a/.github/workflows/Tasmota_build_devel.yml +++ b/.github/workflows/Tasmota_build_devel.yml @@ -3,7 +3,7 @@ name: Build_firmware_development on: workflow_dispatch: # Manually start a workflow push: - branches: development + branches: development-off paths-ignore: - '.github/**' # Ignore changes towards the .github directory - '**.md' # Do no build if *.md files changes From 0d433117824480cfa31e16016362c68b3e75771f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 25 Nov 2021 15:47:09 +0100 Subject: [PATCH 108/185] Update Tasmota_build_devel.yml --- .github/workflows/Tasmota_build_devel.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Tasmota_build_devel.yml b/.github/workflows/Tasmota_build_devel.yml index 83788c8c8..c0b4abd37 100644 --- a/.github/workflows/Tasmota_build_devel.yml +++ b/.github/workflows/Tasmota_build_devel.yml @@ -1,4 +1,4 @@ -name: Build_firmware_development +name: Build_firmware_development_cache on: workflow_dispatch: # Manually start a workflow @@ -1360,7 +1360,7 @@ jobs: [ ! -f ./mv_firmware/firmware/* ] || mv ./mv_firmware/firmware/* ./firmware/tasmota/languages/ - name: Display files to transfer run: ls -R ./* - - name: Push Firmware files to tmp repo + - name: Push Firmware files to tmp_copy repo uses: Jason2866/copy_file_to_another_repo_action@main env: API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }} From 8faa144d04389286890668fe8db2122b5d324a24 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Thu, 25 Nov 2021 19:46:02 +0100 Subject: [PATCH 109/185] Berry static methods --- lib/libesp32/Berry/src/be_bytecode.c | 4 +-- lib/libesp32/Berry/src/be_class.c | 5 +++- lib/libesp32/Berry/src/be_class.h | 2 +- lib/libesp32/Berry/src/be_constobj.h | 20 +++++++++++++++ lib/libesp32/Berry/src/be_gc.c | 2 +- lib/libesp32/Berry/src/be_map.c | 4 ++- lib/libesp32/Berry/src/be_object.h | 31 ++++++++++++---------- lib/libesp32/Berry/src/be_parser.c | 34 +++++++++++++------------ lib/libesp32/Berry/src/be_solidifylib.c | 14 +++++++--- lib/libesp32/Berry/src/be_string.c | 10 ++++++-- lib/libesp32/Berry/src/be_vm.c | 28 ++++++++++++++++---- 11 files changed, 108 insertions(+), 46 deletions(-) diff --git a/lib/libesp32/Berry/src/be_bytecode.c b/lib/libesp32/Berry/src/be_bytecode.c index 521317e63..9f9283fbe 100644 --- a/lib/libesp32/Berry/src/be_bytecode.c +++ b/lib/libesp32/Berry/src/be_bytecode.c @@ -23,7 +23,7 @@ #define MAGIC_NUMBER1 0xBE #define MAGIC_NUMBER2 0xCD #define MAGIC_NUMBER3 0xFE -#define BYTECODE_VERSION 2 +#define BYTECODE_VERSION 3 #define USE_64BIT_INT (BE_INTGER_TYPE == 2 \ || BE_INTGER_TYPE == 1 && LONG_MAX == 9223372036854775807L) @@ -425,7 +425,7 @@ static void load_class(bvm *vm, void *fp, bvalue *v, int version) be_incrtop(vm); if (load_proto(vm, fp, (bproto**)&var_toobj(value), -3, version)) { /* actual method */ - be_method_bind(vm, c, name, var_toobj(value)); + be_method_bind(vm, c, name, var_toobj(value), bfalse); } else { /* no proto, static member set to nil */ be_member_bind(vm, c, name, bfalse); diff --git a/lib/libesp32/Berry/src/be_class.c b/lib/libesp32/Berry/src/be_class.c index c8c826371..a960d4b24 100644 --- a/lib/libesp32/Berry/src/be_class.c +++ b/lib/libesp32/Berry/src/be_class.c @@ -75,7 +75,7 @@ void be_member_bind(bvm *vm, bclass *c, bstring *name, bbool var) } } -void be_method_bind(bvm *vm, bclass *c, bstring *name, bproto *p) +void be_method_bind(bvm *vm, bclass *c, bstring *name, bproto *p, bbool is_static) { bclosure *cl; bvalue *attr; @@ -87,6 +87,9 @@ void be_method_bind(bvm *vm, bclass *c, bstring *name, bproto *p) cl = be_newclosure(vm, p->nupvals); cl->proto = p; var_setclosure(attr, cl); + if (is_static) { + func_setstatic(attr); + } } void be_prim_method_bind(bvm *vm, bclass *c, bstring *name, bntvfunc f) diff --git a/lib/libesp32/Berry/src/be_class.h b/lib/libesp32/Berry/src/be_class.h index 8bc0a6af7..59abbab30 100644 --- a/lib/libesp32/Berry/src/be_class.h +++ b/lib/libesp32/Berry/src/be_class.h @@ -53,7 +53,7 @@ bclass* be_newclass(bvm *vm, bstring *name, bclass *super); void be_class_compress(bvm *vm, bclass *c); int be_class_attribute(bvm *vm, bclass *c, bstring *attr); void be_member_bind(bvm *vm, bclass *c, bstring *name, bbool var); -void be_method_bind(bvm *vm, bclass *c, bstring *name, bproto *p); +void be_method_bind(bvm *vm, bclass *c, bstring *name, bproto *p, bbool is_static); void be_prim_method_bind(bvm *vm, bclass *c, bstring *name, bntvfunc f); void be_closure_method_bind(bvm *vm, bclass *c, bstring *name, bclosure *cl); int be_class_closure_count(bclass *c); diff --git a/lib/libesp32/Berry/src/be_constobj.h b/lib/libesp32/Berry/src/be_constobj.h index 0e8f1081c..d3f1f5764 100644 --- a/lib/libesp32/Berry/src/be_constobj.h +++ b/lib/libesp32/Berry/src/be_constobj.h @@ -38,6 +38,11 @@ extern "C" { .type = BE_FUNCTION \ } +#define be_const_static_func(_func) { \ + .v.nf = (_func), \ + .type = BE_FUNCTION | BE_FUNC_STATIC \ +} + #define be_const_nil() { \ .v.i = 0, \ .type = BE_NIL \ @@ -88,6 +93,11 @@ extern "C" { .type = BE_CLOSURE \ } +#define be_const_static_closure(_closure) { \ + .v.c = &(_closure), \ + .type = BE_CLOSURE | BE_FUNC_STATIC \ +} + #define be_const_module(_module) { \ .v.c = &(_module), \ .type = BE_MODULE \ @@ -251,6 +261,11 @@ const bntvmodule be_native_module(_module) = { \ BE_FUNCTION \ } +#define be_const_static_func(_func) { \ + bvaldata(_func), \ + BE_FUNCTION | BE_FUNC_STATIC \ +} + #define be_const_nil() { \ bvaldata(0), \ BE_NIL \ @@ -301,6 +316,11 @@ const bntvmodule be_native_module(_module) = { \ BE_CLOSURE \ } +#define be_const_static_closure(_closure) { \ + bvaldata(&(_closure)), \ + BE_CLOSURE | BE_FUNC_STATIC \ +} + #define be_const_module(_module) { \ bvaldata(&(_module)), \ BE_MODULE \ diff --git a/lib/libesp32/Berry/src/be_gc.c b/lib/libesp32/Berry/src/be_gc.c index c0bcf0c5a..b3cf7ab98 100644 --- a/lib/libesp32/Berry/src/be_gc.c +++ b/lib/libesp32/Berry/src/be_gc.c @@ -348,7 +348,7 @@ static void free_instance(bvm *vm, bgcobject *obj) static void free_object(bvm *vm, bgcobject *obj) { - switch (obj->type) { + switch (var_type(obj)) { case BE_STRING: free_lstring(vm, obj); break; /* long string */ case BE_CLASS: be_free(vm, obj, sizeof(bclass)); break; case BE_INSTANCE: free_instance(vm, obj); break; diff --git a/lib/libesp32/Berry/src/be_map.c b/lib/libesp32/Berry/src/be_map.c index a11614680..004406f46 100644 --- a/lib/libesp32/Berry/src/be_map.c +++ b/lib/libesp32/Berry/src/be_map.c @@ -346,5 +346,7 @@ bmapnode* be_map_val2node(bvalue *value) void be_map_release(bvm *vm, bmap *map) { (void)vm; - resize(vm, map, map->count ? map->count : 1); + if (!gc_isconst(map)) { + resize(vm, map, map->count ? map->count : 1); + } } diff --git a/lib/libesp32/Berry/src/be_object.h b/lib/libesp32/Berry/src/be_object.h index f5b878531..4c8cbf1ab 100644 --- a/lib/libesp32/Berry/src/be_object.h +++ b/lib/libesp32/Berry/src/be_object.h @@ -11,25 +11,30 @@ #include "berry.h" /* basic types, do not change value */ -#define BE_NONE (-1) /* unknown type */ -#define BE_COMPTR (-2) /* common pointer */ -#define BE_INDEX (-3) /* index for instance variable, previously BE_INT */ #define BE_NIL 0 #define BE_INT 1 #define BE_REAL 2 #define BE_BOOL 3 -#define BE_FUNCTION 4 -#define BE_STRING 5 /* from this type can be gced, see BE_GCOBJECT */ -#define BE_CLASS 6 -#define BE_INSTANCE 7 -#define BE_PROTO 8 -#define BE_LIST 9 -#define BE_MAP 10 -#define BE_MODULE 11 -#define BE_COMOBJ 12 /* common object */ +#define BE_NONE 4 /* unknown type */ +#define BE_COMPTR 5 /* common pointer */ +#define BE_INDEX 6 /* index for instance variable, previously BE_INT */ +#define BE_FUNCTION 7 +#define BE_STRING 8 /* from this type can be gced, see BE_GCOBJECT */ +#define BE_CLASS 9 +#define BE_INSTANCE 10 +#define BE_PROTO 11 +#define BE_LIST 12 +#define BE_MAP 13 +#define BE_MODULE 14 +#define BE_COMOBJ 15 /* common object */ #define BE_NTVFUNC ((0 << 5) | BE_FUNCTION) #define BE_CLOSURE ((1 << 5) | BE_FUNCTION) #define BE_NTVCLOS ((2 << 5) | BE_FUNCTION) +#define BE_FUNC_STATIC (1 << 7) + +#define func_isstatic(o) (((o)->type & BE_FUNC_STATIC) != 0) +#define func_setstatic(o) ((o)->type |= BE_FUNC_STATIC) +#define func_clearstatic(o) ((o)->type &= ~BE_FUNC_STATIC) #define array_count(a) (sizeof(a) / sizeof((a)[0])) @@ -187,7 +192,7 @@ typedef const char* (*breader)(void*, size_t*); #define cast_bool(_v) cast(bbool, _v) #define basetype(_t) ((_t) & 0x1F) -#define var_type(_v) ((_v)->type) +#define var_type(_v) ((_v)->type & 0x7F) #define var_basetype(_v) basetype((_v)->type) #define var_istype(_v, _t) (var_type(_v) == _t) #define var_settype(_v, _t) ((_v)->type = _t) diff --git a/lib/libesp32/Berry/src/be_parser.c b/lib/libesp32/Berry/src/be_parser.c index 664f24b92..d2f2d7af5 100644 --- a/lib/libesp32/Berry/src/be_parser.c +++ b/lib/libesp32/Berry/src/be_parser.c @@ -1422,12 +1422,28 @@ static void class_static_assignment_expr(bparser *parser, bexpdesc *e, bstring * } } +static void classdef_stmt(bparser *parser, bclass *c, bbool is_static) +{ + bexpdesc e; + bstring *name; + bproto *proto; + /* 'def' ID '(' varlist ')' block 'end' */ + scan_next_token(parser); /* skip 'def' */ + name = func_name(parser, &e, 1); + check_class_attr(parser, c, name); + proto = funcbody(parser, name, is_static ? 0 : FUNC_METHOD); + be_method_bind(parser->vm, c, proto->name, proto, is_static); + be_stackpop(parser->vm, 1); +} + static void classstatic_stmt(bparser *parser, bclass *c, bexpdesc *e) { bstring *name; /* 'static' ID ['=' expr] {',' ID ['=' expr] } */ scan_next_token(parser); /* skip 'static' */ - if (match_id(parser, name) != NULL) { + if (next_type(parser) == KeyDef) { /* 'static' 'def' ... */ + classdef_stmt(parser, c, btrue); + } else if (match_id(parser, name) != NULL) { check_class_attr(parser, c, name); be_member_bind(parser->vm, c, name, bfalse); class_static_assignment_expr(parser, e, name); @@ -1446,20 +1462,6 @@ static void classstatic_stmt(bparser *parser, bclass *c, bexpdesc *e) } } -static void classdef_stmt(bparser *parser, bclass *c) -{ - bexpdesc e; - bstring *name; - bproto *proto; - /* 'def' ID '(' varlist ')' block 'end' */ - scan_next_token(parser); /* skip 'def' */ - name = func_name(parser, &e, 1); - check_class_attr(parser, c, name); - proto = funcbody(parser, name, FUNC_METHOD); - be_method_bind(parser->vm, c, proto->name, proto); - be_stackpop(parser->vm, 1); -} - static void class_inherit(bparser *parser, bexpdesc *e) { if (next_type(parser) == OptColon) { /* ':' */ @@ -1479,7 +1481,7 @@ static void class_block(bparser *parser, bclass *c, bexpdesc *e) switch (next_type(parser)) { case KeyVar: classvar_stmt(parser, c); break; case KeyStatic: classstatic_stmt(parser, c, e); break; - case KeyDef: classdef_stmt(parser, c); break; + case KeyDef: classdef_stmt(parser, c, bfalse); break; case OptSemic: scan_next_token(parser); break; default: push_error(parser, "unexpected token '%s'", token2str(parser)); diff --git a/lib/libesp32/Berry/src/be_solidifylib.c b/lib/libesp32/Berry/src/be_solidifylib.c index ec0b60ca1..3dba26768 100644 --- a/lib/libesp32/Berry/src/be_solidifylib.c +++ b/lib/libesp32/Berry/src/be_solidifylib.c @@ -41,6 +41,9 @@ static void m_solidify_bvalue(bvm *vm, bvalue * value, const char *classname, co static void m_solidify_map(bvm *vm, bmap * map, const char *class_name) { + // compact first + be_map_release(vm, map); + logfmt(" be_nested_map(%i,\n", map->count); logfmt(" ( (struct bmapnode*) &(const bmapnode[]) {\n"); @@ -128,7 +131,8 @@ static void m_solidify_bvalue(bvm *vm, bvalue * value, const char *classname, co } break; case BE_CLOSURE: - logfmt("be_const_closure(%s%s%s_closure)", + logfmt("be_const_%sclosure(%s%s%s_closure)", + func_isstatic(value) ? "static_" : "", classname ? classname : "", classname ? "_" : "", str(((bclosure*) var_toobj(value))->proto->name)); break; @@ -139,7 +143,9 @@ static void m_solidify_bvalue(bvm *vm, bvalue * value, const char *classname, co logfmt("be_const_comptr(&be_ntv_%s_%s)", classname ? classname : "unknown", key ? key : "unknown"); break; case BE_NTVFUNC: - logfmt("be_const_func(be_ntv_%s_%s)", classname ? classname : "unknown", key ? key : "unknown"); + logfmt("be_const_%sfunc(be_ntv_%s_%s)", + func_isstatic(value) ? "static_" : "", + classname ? classname : "unknown", key ? key : "unknown"); break; case BE_INSTANCE: { @@ -199,7 +205,7 @@ static void m_solidify_proto_inner_class(bvm *vm, bproto *pr, int builtins) static void m_solidify_proto(bvm *vm, bproto *pr, const char * func_name, int builtins, int indent) { // const char * func_name = str(pr->name); - const char * func_source = str(pr->source); + // const char * func_source = str(pr->source); logfmt("%*sbe_nested_proto(\n", indent, ""); indent += 2; @@ -345,7 +351,7 @@ static void m_solidify_subclass(bvm *vm, bclass *cl, int builtins) logfmt(" NULL,\n"); } - logfmt(" (be_nested_const_str(\"%s\", %i, %i))\n", class_name, be_strhash(cl->name), str_len(cl->name)); + logfmt(" (be_nested_str_literal(\"%s\"))\n", class_name); logfmt(");\n"); } diff --git a/lib/libesp32/Berry/src/be_string.c b/lib/libesp32/Berry/src/be_string.c index b6890a937..798437420 100644 --- a/lib/libesp32/Berry/src/be_string.c +++ b/lib/libesp32/Berry/src/be_string.c @@ -57,12 +57,18 @@ int be_eqstr(bstring *s1, bstring *s2) } /* const short strings */ if (gc_isconst(s1) || gc_isconst(s2)) { /* one of the two string is short const */ - if (cast(bcstring*, s1)->hash && cast(bcstring*, s2)->hash) { - return 0; /* if they both have a hash, then we know they are different */ + uint32_t hash1 = cast(bcstring*, s1)->hash; + uint32_t hash2 = cast(bcstring*, s2)->hash; + if (hash1 && hash2 && hash1 != hash2) { + return 0; /* if hash differ, since we know both are non-null */ } + /* if hash are equals, there might be a chance that they are different */ + /* This can happen with solidified code that a same string is present more than once */ + /* so just considering that two strings with the same hash must be same pointer, this is no more true */ return !strcmp(str(s1), str(s2)); } + /* if both strings are in-memory, they can't be equal without having the same pointer */ return 0; } diff --git a/lib/libesp32/Berry/src/be_vm.c b/lib/libesp32/Berry/src/be_vm.c index 39ae6521e..f00cc128a 100644 --- a/lib/libesp32/Berry/src/be_vm.c +++ b/lib/libesp32/Berry/src/be_vm.c @@ -854,16 +854,29 @@ newframe: /* a new call frame */ bvalue *a = RA(); *a = a_temp; if (basetype(type) == BE_FUNCTION) { - /* check if the object is a superinstance, if so get the lowest possible subclass */ - while (obj->sub) { - obj = obj->sub; + if (func_isstatic(a)) { + /* static method, don't bother with the instance */ + a[1] = a_temp; + var_settype(a, NOT_METHOD); + } else { + /* this is a real method (i.e. non-static) */ + /* check if the object is a superinstance, if so get the lowest possible subclass */ + while (obj->sub) { + obj = obj->sub; + } + var_setinstance(&a[1], obj); /* replace superinstance by lowest subinstance */ } - var_setinstance(&a[1], obj); /* replace superinstance by lowest subinstance */ } else { vm_error(vm, "attribute_error", "class '%s' has no method '%s'", str(be_instance_name(obj)), str(var_tostr(c))); } + } else if (var_isclass(b) && var_isstr(c)) { + class_attribute(vm, b, c, &a_temp); + reg = vm->reg; + bvalue *a = RA(); + a[1] = a_temp; + var_settype(a, NOT_METHOD); } else if (var_ismodule(b) && var_isstr(c)) { module_attribute(vm, b, c, &a_temp); reg = vm->reg; @@ -893,9 +906,14 @@ newframe: /* a new call frame */ dispatch(); } if (var_isclass(a) && var_isstr(b)) { + /* if value is a function, we mark it as a static to distinguish from methods */ bclass *obj = var_toobj(a); bstring *attr = var_tostr(b); - if (!be_class_setmember(vm, obj, attr, c)) { + bvalue c_static = *c; + if (var_isfunction(&c_static)) { + c_static.type = func_setstatic(&c_static); + } + if (!be_class_setmember(vm, obj, attr, &c_static)) { reg = vm->reg; vm_error(vm, "attribute_error", "class '%s' cannot assign to static attribute '%s'", From 711ca5a277d0dbd4111f9e3a666dd9d47cbd77cd Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Thu, 25 Nov 2021 20:00:07 +0100 Subject: [PATCH 110/185] OTA follows redirects --- CHANGELOG.md | 2 +- lib/libesp32/Berry-HttpClientLight/src/HTTPUpdateLight.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 82bb831ab..0bdc15b4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ All notable changes to this project will be documented in this file. - Preliminary support for Tasmota Apps (.tapp extesions) - Berry support for neopixel (WS2812, SK6812) - Command ``IfxPeriod `` to overrule ``Teleperiod`` for Influx messages (#13750) -- OTA over HTTPS +- OTA over HTTPS (ESP32x only) ### Changed - ESP8266 Gratuitous ARP enabled and set to 60 seconds (#13623) diff --git a/lib/libesp32/Berry-HttpClientLight/src/HTTPUpdateLight.cpp b/lib/libesp32/Berry-HttpClientLight/src/HTTPUpdateLight.cpp index 958180e97..694502ea5 100644 --- a/lib/libesp32/Berry-HttpClientLight/src/HTTPUpdateLight.cpp +++ b/lib/libesp32/Berry-HttpClientLight/src/HTTPUpdateLight.cpp @@ -39,13 +39,13 @@ enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_D HTTPUpdateLight::HTTPUpdateLight(void) : _httpClientTimeout(8000), _ledPin(-1) { - _followRedirects = HTTPC_DISABLE_FOLLOW_REDIRECTS; + _followRedirects = HTTPC_STRICT_FOLLOW_REDIRECTS; } HTTPUpdateLight::HTTPUpdateLight(int httpClientTimeout) : _httpClientTimeout(httpClientTimeout), _ledPin(-1) { - _followRedirects = HTTPC_DISABLE_FOLLOW_REDIRECTS; + _followRedirects = HTTPC_STRICT_FOLLOW_REDIRECTS; } HTTPUpdateLight::~HTTPUpdateLight(void) From 498aa9b2b3a7b958e69b6748d0f187f628c9f9d2 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Thu, 25 Nov 2021 20:09:04 +0100 Subject: [PATCH 111/185] Update static functions, test and grammar --- lib/libesp32/Berry/tests/class_const.be | 30 +++++++++++++++++++-- lib/libesp32/Berry/tools/grammar/berry.ebnf | 2 +- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/lib/libesp32/Berry/tests/class_const.be b/lib/libesp32/Berry/tests/class_const.be index dda433174..7c986bff0 100644 --- a/lib/libesp32/Berry/tests/class_const.be +++ b/lib/libesp32/Berry/tests/class_const.be @@ -65,8 +65,26 @@ assert(type(a.g) == 'function') assert(type(a.h) == 'function') assert_attribute_error("a.g(1,2)") -assert(a.h(1) == 'instance') -# A.h(1) - error +assert(a.h(1) == 'int') +assert(A.h(1) == 'int') + + +class A + var a + static def g(x, y) return [x,y] end + static h = def (x, y) return [x,y] end + def init() self.a = 1 end + def f(x, y) return type(self) end +end +a=A() +assert(type(a.g) == 'function') +assert(type(a.h) == 'function') +assert(type(A.g) == 'function') +assert(type(A.h) == 'function') +assert(a.g(1,2) == [1,2]) +assert(a.h(1,2) == [1,2]) +assert(A.g(1,2) == [1,2]) +assert(A.h(1,2) == [1,2]) #- test static initializers -# class A @@ -91,3 +109,11 @@ assert(a.f == [1]) assert(a.g == A.g) assert(a.aa == nil) assert(a.ab == nil) + +#- used to fail for subclasses -# +class A static a=1 end +class B:A static a=A def f() end static b=1 static c=A end +assert(A.a == 1) +assert(B.a == A) +assert(B.b == 1) +assert(B.c == A) diff --git a/lib/libesp32/Berry/tools/grammar/berry.ebnf b/lib/libesp32/Berry/tools/grammar/berry.ebnf index 1ca79a763..1b8889f80 100644 --- a/lib/libesp32/Berry/tools/grammar/berry.ebnf +++ b/lib/libesp32/Berry/tools/grammar/berry.ebnf @@ -17,7 +17,7 @@ func_body = '(' [arg_field {',' arg_field}] ')' block 'end'; arg_field = ['*'] ID; (* class define statement *) class_stmt = 'class' ID [':' ID] class_block 'end'; -class_block = {'var' ID {',' ID} | 'static' ID ['=' expr] {',' ID ['=' expr] } | func_stmt}; +class_block = {'var' ID {',' ID} | 'static' ID ['=' expr] {',' ID ['=' expr] } | 'static' func_stmt | func_stmt}; import_stmt = 'import' (ID (['as' ID] | {',' ID}) | STRING 'as' ID); (* exceptional handling statement *) try_stmt = 'try' block except_block {except_block} 'end'; From 3e9b2c9a75a7b1dc9fea4e4095c871edacbae6ea Mon Sep 17 00:00:00 2001 From: stefanbode Date: Thu, 25 Nov 2021 21:23:46 +0100 Subject: [PATCH 112/185] Added Venetian blind support --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bdc15b4a..ade4199e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file. ## [10.0.0.3] ### Added +- Shutter support for venetian blinds with tilt control - Autoconfiguration for ESP32 and variants - ESP32 fix leftover GPIO configuration after restart - ESP32 Proof of Concept Sonoff SPM with limited functionality (switching and energy monitoring) (#13447) From 2ae03c6e43fc399e5aad09cc2d1dc240fb6d4bd6 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Thu, 25 Nov 2021 22:57:37 +0100 Subject: [PATCH 113/185] Berry add ``import re`` regex module --- CHANGELOG.md | 1 + lib/libesp32/Berry/default/be_modtab.c | 2 + lib/libesp32/Berry/default/be_re_lib.c | 218 +++++++++++++++++++++ lib/libesp32/re1.5/LICENSE | 27 +++ lib/libesp32/re1.5/Makefile | 44 +++++ lib/libesp32/re1.5/README | 48 +++++ lib/libesp32/re1.5/backtrack.c | 117 +++++++++++ lib/libesp32/re1.5/charclass.c | 33 ++++ lib/libesp32/re1.5/cleanmarks.c | 39 ++++ lib/libesp32/re1.5/compile.c | 179 +++++++++++++++++ lib/libesp32/re1.5/compilecode.c | 256 +++++++++++++++++++++++++ lib/libesp32/re1.5/dumpcode.c | 65 +++++++ lib/libesp32/re1.5/library.json | 13 ++ lib/libesp32/re1.5/main.c | 150 +++++++++++++++ lib/libesp32/re1.5/parse.y | 229 ++++++++++++++++++++++ lib/libesp32/re1.5/pike.c | 176 +++++++++++++++++ lib/libesp32/re1.5/re1.5.h | 162 ++++++++++++++++ lib/libesp32/re1.5/recursive.c | 79 ++++++++ lib/libesp32/re1.5/recursiveloop.c | 86 +++++++++ lib/libesp32/re1.5/run-tests | 164 ++++++++++++++++ lib/libesp32/re1.5/sub.c | 55 ++++++ lib/libesp32/re1.5/thompson.c | 152 +++++++++++++++ lib/libesp32/re1.5/util.c | 24 +++ tasmota/xdrv_52_0_berry_struct.ino | 2 + 24 files changed, 2321 insertions(+) create mode 100644 lib/libesp32/Berry/default/be_re_lib.c create mode 100644 lib/libesp32/re1.5/LICENSE create mode 100644 lib/libesp32/re1.5/Makefile create mode 100644 lib/libesp32/re1.5/README create mode 100644 lib/libesp32/re1.5/backtrack.c create mode 100644 lib/libesp32/re1.5/charclass.c create mode 100644 lib/libesp32/re1.5/cleanmarks.c create mode 100644 lib/libesp32/re1.5/compile.c create mode 100644 lib/libesp32/re1.5/compilecode.c create mode 100644 lib/libesp32/re1.5/dumpcode.c create mode 100644 lib/libesp32/re1.5/library.json create mode 100644 lib/libesp32/re1.5/main.c create mode 100644 lib/libesp32/re1.5/parse.y create mode 100644 lib/libesp32/re1.5/pike.c create mode 100644 lib/libesp32/re1.5/re1.5.h create mode 100644 lib/libesp32/re1.5/recursive.c create mode 100644 lib/libesp32/re1.5/recursiveloop.c create mode 100755 lib/libesp32/re1.5/run-tests create mode 100644 lib/libesp32/re1.5/sub.c create mode 100644 lib/libesp32/re1.5/thompson.c create mode 100644 lib/libesp32/re1.5/util.c diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bdc15b4a..4dc82aa10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ All notable changes to this project will be documented in this file. - Berry support for neopixel (WS2812, SK6812) - Command ``IfxPeriod `` to overrule ``Teleperiod`` for Influx messages (#13750) - OTA over HTTPS (ESP32x only) +- Berry add ``import re`` regex module ### Changed - ESP8266 Gratuitous ARP enabled and set to 60 seconds (#13623) diff --git a/lib/libesp32/Berry/default/be_modtab.c b/lib/libesp32/Berry/default/be_modtab.c index 5c704b142..5f04457ac 100644 --- a/lib/libesp32/Berry/default/be_modtab.c +++ b/lib/libesp32/Berry/default/be_modtab.c @@ -25,6 +25,7 @@ be_extern_native_module(strict); /* Tasmota specific */ be_extern_native_module(python_compat); +be_extern_native_module(re); be_extern_native_module(persist); be_extern_native_module(autoconf); be_extern_native_module(tapp); @@ -87,6 +88,7 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = { /* user-defined modules register start */ &be_native_module(python_compat), + &be_native_module(re), &be_native_module(path), &be_native_module(persist), #ifdef USE_AUTOCONF diff --git a/lib/libesp32/Berry/default/be_re_lib.c b/lib/libesp32/Berry/default/be_re_lib.c new file mode 100644 index 000000000..2c94c3440 --- /dev/null +++ b/lib/libesp32/Berry/default/be_re_lib.c @@ -0,0 +1,218 @@ +/******************************************************************** + * Tasmota lib + * + * To use: `import re` + * + * Regex using re1.5 + *******************************************************************/ +#include "be_constobj.h" +#include "be_mem.h" +#include "re1.5.h" + +/******************************************************************** +# Berry skeleton for `re` module +# + +class re_pattern + var _p # comobj containing the compiled bytecode for the pattern + + def search() end + def match() end + def split() end +end + +re = module("re") + +re.compile = def (regex_str) end # native +re.match = def (regex_str, str) end # native +re.search = def (regex_str, str) end # native + + +*******************************************************************/ + +extern const bclass be_class_re_pattern; + +int be_free_comobj(bvm* vm) { + int argc = be_top(vm); + if (argc > 0) { + void * obj = be_tocomptr(vm, 1); + if (obj != NULL) { be_os_free(obj); } + } + be_return_nil(vm); +} + +// Native functions be_const_func() +// Berry: `re.compile(pattern:string) -> instance(be_pattern)` +int be_re_compile(bvm *vm) { + int32_t argc = be_top(vm); // Get the number of arguments + if (argc >= 1 && be_isstring(vm, 1)) { + const char * regex_str = be_tostring(vm, 1); + int sz = re1_5_sizecode(regex_str); + if (sz < 0) { + be_raise(vm, "internal_error", "error in regex"); + } + + ByteProg *code = be_os_malloc(sizeof(ByteProg) + sz); + int ret = re1_5_compilecode(code, regex_str); + if (ret != 0) { + be_raise(vm, "internal_error", "error in regex"); + } + be_pushntvclass(vm, &be_class_re_pattern); + be_call(vm, 0); + be_newcomobj(vm, code, &be_free_comobj); + be_setmember(vm, -2, "_p"); + be_pop(vm, 1); + be_return(vm); + } + be_raise(vm, "type_error", NULL); +} + + +int be_re_match_search_run(bvm *vm, ByteProg *code, const char *hay, bbool is_anchored) { + Subject subj = {hay, hay + strlen(hay)}; + + int sub_els = (code->sub + 1) * 2; + const char *sub[sub_els]; + + if (!re1_5_recursiveloopprog(code, &subj, sub, sub_els, is_anchored)) { + be_return_nil(vm); // no match + } + + be_newobject(vm, "list"); + int k; + for(k = sub_els; k > 0; k--) + if(sub[k-1]) + break; + for (int i = 0; i < k; i += 2) { + be_pushnstring(vm, sub[i], sub[i+1] - sub[i]); + be_data_push(vm, -2); + be_pop(vm, 1); + } + be_pop(vm, 1); // remove list + be_return(vm); // return list object +} + +int be_re_match_search(bvm *vm, bbool is_anchored) { + int32_t argc = be_top(vm); // Get the number of arguments + if (argc >= 2 && be_isstring(vm, 1) && be_isstring(vm, 2)) { + const char * regex_str = be_tostring(vm, 1); + const char * hay = be_tostring(vm, 2); + int sz = re1_5_sizecode(regex_str); + if (sz < 0) { + be_raise(vm, "internal_error", "error in regex"); + } + + ByteProg *code = be_os_malloc(sizeof(ByteProg) + sz); + int ret = re1_5_compilecode(code, regex_str); + if (ret != 0) { + be_raise(vm, "internal_error", "error in regex"); + } + return be_re_match_search_run(vm, code, hay, is_anchored); + } + be_raise(vm, "type_error", NULL); +} + +// Berry: `re.match(value:int | s:string) -> nil` +int be_re_match(bvm *vm) { + return be_re_match_search(vm, btrue); +} +// Berry: `re.search(value:int | s:string) -> nil` +int be_re_search(bvm *vm) { + return be_re_match_search(vm, bfalse); +} + +// Berry: `re_pattern.search(s:string) -> list(string)` +int re_pattern_search(bvm *vm) { + int32_t argc = be_top(vm); // Get the number of arguments + if (argc >= 2 && be_isstring(vm, 2)) { + const char * hay = be_tostring(vm, 2); + be_getmember(vm, 1, "_p"); + ByteProg * code = (ByteProg*) be_tocomptr(vm, -1); + return be_re_match_search_run(vm, code, hay, bfalse); + } + be_raise(vm, "type_error", NULL); +} + +// Berry: `re_pattern.match(s:string) -> list(string)` +int re_pattern_match(bvm *vm) { + int32_t argc = be_top(vm); // Get the number of arguments + if (argc >= 2 && be_isstring(vm, 2)) { + const char * hay = be_tostring(vm, 2); + be_getmember(vm, 1, "_p"); + ByteProg * code = (ByteProg*) be_tocomptr(vm, -1); + return be_re_match_search_run(vm, code, hay, btrue); + } + be_raise(vm, "type_error", NULL); +} + +// Berry: `re_pattern.split(s:string) -> list(string)` +int re_pattern_split(bvm *vm) { + int32_t argc = be_top(vm); // Get the number of arguments + if (argc >= 2 && be_isstring(vm, 2)) { + const char * hay = be_tostring(vm, 2); + be_getmember(vm, 1, "_p"); + ByteProg * code = (ByteProg*) be_tocomptr(vm, -1); + + Subject subj = {hay, hay + strlen(hay)}; + + int sub_els = (code->sub + 1) * 2; + const char *sub[sub_els]; + + be_newobject(vm, "list"); + while (1) { + if (!re1_5_recursiveloopprog(code, &subj, sub, sub_els, bfalse)) { + be_pushnstring(vm, subj.begin, subj.end - subj.begin); + be_data_push(vm, -2); + be_pop(vm, 1); + break; + } + + if (sub[0] == NULL || sub[1] == NULL || sub[0] == sub[1]) { + be_raise(vm, "internal_error", "can't match"); + } + be_pushnstring(vm, subj.begin, sub[0] - subj.begin); + be_data_push(vm, -2); + be_pop(vm, 1); + subj.begin = sub[1]; + } + be_pop(vm, 1); // remove list + be_return(vm); // return list object + + } + be_raise(vm, "type_error", NULL); +} + +/******************************************************************** +** Solidified module: re +********************************************************************/ +be_local_module(re, + "re", + be_nested_map(3, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_nested_key("compile", 1000265118, 7, -1), be_const_func(be_re_compile) }, + { be_nested_key("search", -2144130903, 6, 2), be_const_func(be_re_search) }, + { be_nested_key("match", 2116038550, 5, -1), be_const_func(be_re_match) }, + })) +); +BE_EXPORT_VARIABLE be_define_const_native_module(re); +/********************************************************************/ + +// =================================================================== + +/******************************************************************** +** Solidified class: re_pattern +********************************************************************/ +be_local_class(re_pattern, + 1, + NULL, + be_nested_map(4, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_nested_key("_p", 1594591802, 2, -1), be_const_var(0) }, + { be_nested_key("search", -2144130903, 6, -1), be_const_func(re_pattern_search) }, + { be_nested_key("match", 2116038550, 5, 0), be_const_func(re_pattern_match) }, + { be_nested_key("split", -2017972765, 5, -1), be_const_func(re_pattern_split) }, + })), + (be_nested_const_str("re_pattern", 2041968961, 10)) +); +/*******************************************************************/ + diff --git a/lib/libesp32/re1.5/LICENSE b/lib/libesp32/re1.5/LICENSE new file mode 100644 index 000000000..85c4185d4 --- /dev/null +++ b/lib/libesp32/re1.5/LICENSE @@ -0,0 +1,27 @@ +// Copyright (c) 2007-2009 Russ Cox, Google Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google, Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/lib/libesp32/re1.5/Makefile b/lib/libesp32/re1.5/Makefile new file mode 100644 index 000000000..6fe6d3f3c --- /dev/null +++ b/lib/libesp32/re1.5/Makefile @@ -0,0 +1,44 @@ +# Copyright 2007-2009 Russ Cox. All Rights Reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +CC=gcc + +CFLAGS=-g -Wall -Os +# Comment out when developing/testing +#CFLAGS=-DDEBUG -g -Wall -O0 + +TARGET=re +OFILES=\ + backtrack.o\ + compile.o\ + main.o\ + pike.o\ + recursive.o\ + recursiveloop.o\ + sub.o\ + thompson.o\ + compilecode.o\ + dumpcode.o\ + charclass.o\ + cleanmarks.o\ + util.o\ + y.tab.o\ + +HFILES=\ + re1.5.h\ + +$(TARGET): $(OFILES) + $(CC) $(CFLAGS) -o $(TARGET) $(OFILES) + +%.o: %.c $(HFILES) + $(CC) -c $(CFLAGS) $*.c + +y.tab.h y.tab.c: parse.y + bison -v -y parse.y + +test: $(TARGET) + ./run-tests $(TFLAGS) + +clean: + rm -f *.o core $(TARGET) y.tab.[ch] y.output diff --git a/lib/libesp32/re1.5/README b/lib/libesp32/re1.5/README new file mode 100644 index 000000000..d116d330d --- /dev/null +++ b/lib/libesp32/re1.5/README @@ -0,0 +1,48 @@ +What is re1.5? +============== + +re1 (http://code.google.com/p/re1/) is "toy regular expression implementation" +by Russel Cox, featuring simplicity and minimal code size unheard of in other +implementations. re2 (http://code.google.com/p/re2/) is "an efficient, +principled regular expression library" by the same author. It is robust, +full-featured, and ... bloated, comparing to re1. + +re1.5 is an attempt to start with re1 codebase and add features required for +minimalistic real-world use, while sticking to the minimal code size and +memory use. + +Why? +==== +re1.5 is intended for use in highly constrained, e.g. embedded, environments, +where offering familiar high-level string matching functionality is still +beneficial. + +Features +======== + +* Like re1, re1.5 retains design where compiled expression can be executed +(matched) by multiple backends, each with its own distinctive design and +runtime properties (complexity and memory usage). +* Unlike re1, regexes are compiled to memory-efficient bytecode. Exact size +of the bytecode can be found prior to compilation (for memory allocation). +* External API functions feature namespace prefix to improve clarity and +avoid name clashes when integrating into other projects. +* Matchers are NUL-char clean and take size of the input string as a param. +* Support for quoted chars in regex. +* Support for ^, $ assertions in regex. +* Support for "match" vs "search" operations, as common in other regex APIs. +* Support for named character classes: \d \D \s \S \w \W. + +TODO +==== + +* Support for repetition operator {n} and {n,m}. +* Support for Unicode (UTF-8). +* Support for matching flags like case-insensitive, dot matches all, +multiline, etc. +* Support for more assertions like \A, \Z. + +Author and License +================== +re1.5 is maintained by Paul Sokolovsky pfalcon at users.sourceforge.net and +licensed under BSD license, just as the original re1. diff --git a/lib/libesp32/re1.5/backtrack.c b/lib/libesp32/re1.5/backtrack.c new file mode 100644 index 000000000..160069c9d --- /dev/null +++ b/lib/libesp32/re1.5/backtrack.c @@ -0,0 +1,117 @@ +// Copyright 2007-2009 Russ Cox. All Rights Reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "re1.5.h" + +typedef struct Thread Thread; +struct Thread +{ + char *pc; + const char *sp; + Sub *sub; +}; + +static Thread +thread(char *pc, const char *sp, Sub *sub) +{ + Thread t = {pc, sp, sub}; + return t; +} + +int +re1_5_backtrack(ByteProg *prog, Subject *input, const char **subp, int nsubp, int is_anchored) +{ + enum { MAX = 1000 }; + Thread ready[MAX]; + int i, nready; + char *pc; + const char *sp; + Sub *sub; + int off; + + /* queue initial thread */ + sub = newsub(nsubp); + for(i=0; isub[i] = nil; + ready[0] = thread(HANDLE_ANCHORED(prog->insts, is_anchored), input->begin, sub); + nready = 1; + + /* run threads in stack order */ + while(nready > 0) { + --nready; /* pop state for next thread to run */ + pc = ready[nready].pc; + sp = ready[nready].sp; + sub = ready[nready].sub; + assert(sub->ref > 0); + for(;;) { + if(inst_is_consumer(*pc)) { + // If we need to match a character, but there's none left, it's fail + if(sp >= input->end) + goto Dead; + } + switch(*pc++) { + case Char: + if(*sp != *pc++) + goto Dead; + case Any: + sp++; + continue; + case Class: + case ClassNot: + if (!_re1_5_classmatch(pc, sp)) + goto Dead; + pc += *(unsigned char*)pc * 2 + 1; + sp++; + continue; + case NamedClass: + if (!_re1_5_namedclassmatch(pc, sp)) + goto Dead; + pc++; + sp++; + continue; + case Match: + for(i=0; isub[i]; + decref(sub); + return 1; + case Jmp: + off = (signed char)*pc++; + pc = pc + off; + continue; + case Split: + if(nready >= MAX) + re1_5_fatal("backtrack overflow"); + off = (signed char)*pc++; + ready[nready++] = thread(pc + off, sp, incref(sub)); +// pc = pc->x; /* continue current thread */ + continue; + case RSplit: + if(nready >= MAX) + re1_5_fatal("backtrack overflow"); + off = (signed char)*pc++; + ready[nready++] = thread(pc, sp, incref(sub)); + pc = pc + off; + continue; + case Save: + off = (unsigned char)*pc++; + sub = update(sub, off, sp); + continue; + case Bol: + if(sp != input->begin) + goto Dead; + continue; + case Eol: + if(sp != input->end) + goto Dead; + continue; + default: + re1_5_fatal("backtrack"); + } + } + Dead: + decref(sub); + } + return 0; +} + diff --git a/lib/libesp32/re1.5/charclass.c b/lib/libesp32/re1.5/charclass.c new file mode 100644 index 000000000..7f6388c93 --- /dev/null +++ b/lib/libesp32/re1.5/charclass.c @@ -0,0 +1,33 @@ +#include "re1.5.h" + +int _re1_5_classmatch(const char *pc, const char *sp) +{ + // pc points to "cnt" byte after opcode + int is_positive = (pc[-1] == Class); + int cnt = *pc++; + while (cnt--) { + if (*sp >= *pc && *sp <= pc[1]) return is_positive; + pc += 2; + } + return !is_positive; +} + +int _re1_5_namedclassmatch(const char *pc, const char *sp) +{ + // pc points to name of class + int off = (*pc >> 5) & 1; + if ((*pc | 0x20) == 'd') { + if (!(*sp >= '0' && *sp <= '9')) { + off ^= 1; + } + } else if ((*pc | 0x20) == 's') { + if (!(*sp == ' ' || (*sp >= '\t' && *sp <= '\r'))) { + off ^= 1; + } + } else { // w + if (!((*sp >= 'A' && *sp <= 'Z') || (*sp >= 'a' && *sp <= 'z') || (*sp >= '0' && *sp <= '9') || *sp == '_')) { + off ^= 1; + } + } + return off; +} diff --git a/lib/libesp32/re1.5/cleanmarks.c b/lib/libesp32/re1.5/cleanmarks.c new file mode 100644 index 000000000..afe0f91d6 --- /dev/null +++ b/lib/libesp32/re1.5/cleanmarks.c @@ -0,0 +1,39 @@ +// Copyright 2014 Paul Sokolovsky. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "re1.5.h" + +void +cleanmarks(ByteProg *prog) +{ + char *pc = prog->insts; + char *end = pc + prog->bytelen; + while (pc < end) { + *pc &= 0x7f; + switch (*pc) { + case Class: + case ClassNot: + pc += (unsigned char)pc[1] * 2; + case NamedClass: + case Jmp: + case Split: + case RSplit: + case Save: + case Char: + pc++; + break; +#ifdef DEBUG + case Bol: + case Eol: + case Any: + case Match: + break; + default: + printf("Unknown instruction 0x%02x pc %ld\n", (unsigned char)*pc, pc - prog->insts); + re1_5_fatal("cleanmarks"); +#endif + } + pc++; + } +} diff --git a/lib/libesp32/re1.5/compile.c b/lib/libesp32/re1.5/compile.c new file mode 100644 index 000000000..c5a995388 --- /dev/null +++ b/lib/libesp32/re1.5/compile.c @@ -0,0 +1,179 @@ +// Copyright 2007-2009 Russ Cox. All Rights Reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +#ifdef DEBUG + +#include "re1.5.h" + +static Inst *pc; +static int count(Regexp*); +static void emit(Regexp*); + +Prog* +compile(Regexp *r) +{ + int n; + Prog *p; + + n = count(r) + 1; + p = mal(sizeof *p + n*sizeof p->start[0]); + p->start = (Inst*)(p+1); + pc = p->start; + emit(r); + pc->opcode = Match; + pc++; + p->len = pc - p->start; + return p; +} + +// how many instructions does r need? +static int +count(Regexp *r) +{ + switch(r->type) { + default: + re1_5_fatal("bad count"); + case Alt: + return 2 + count(r->left) + count(r->right); + case Cat: + return count(r->left) + count(r->right); + case Lit: + case Dot: + return 1; + case Paren: + return 2 + count(r->left); + case Quest: + return 1 + count(r->left); + case Star: + return 2 + count(r->left); + case Plus: + return 1 + count(r->left); + } +} + +static void +emit(Regexp *r) +{ + Inst *p1, *p2, *t; + + switch(r->type) { + default: + re1_5_fatal("bad emit"); + + case Alt: + pc->opcode = Split; + p1 = pc++; + p1->x = pc; + emit(r->left); + pc->opcode = Jmp; + p2 = pc++; + p1->y = pc; + emit(r->right); + p2->x = pc; + break; + + case Cat: + emit(r->left); + emit(r->right); + break; + + case Lit: + pc->opcode = Char; + pc->c = r->ch; + pc++; + break; + + case Dot: + pc++->opcode = Any; + break; + + case Paren: + pc->opcode = Save; + pc->n = 2*r->n; + pc++; + emit(r->left); + pc->opcode = Save; + pc->n = 2*r->n + 1; + pc++; + break; + + case Quest: + pc->opcode = Split; + p1 = pc++; + p1->x = pc; + emit(r->left); + p1->y = pc; + if(r->n) { // non-greedy + t = p1->x; + p1->x = p1->y; + p1->y = t; + } + break; + + case Star: + pc->opcode = Split; + p1 = pc++; + p1->x = pc; + emit(r->left); + pc->opcode = Jmp; + pc->x = p1; + pc++; + p1->y = pc; + if(r->n) { // non-greedy + t = p1->x; + p1->x = p1->y; + p1->y = t; + } + break; + + case Plus: + p1 = pc; + emit(r->left); + pc->opcode = Split; + pc->x = p1; + p2 = pc; + pc++; + p2->y = pc; + if(r->n) { // non-greedy + t = p2->x; + p2->x = p2->y; + p2->y = t; + } + break; + } +} + +void +printprog(Prog *p) +{ + Inst *pc, *e; + + pc = p->start; + e = p->start + p->len; + + for(; pc < e; pc++) { + switch(pc->opcode) { + default: + re1_5_fatal("printprog"); + case Split: + printf("%2d. split %d, %d\n", (int)(pc-p->start), (int)(pc->x-p->start), (int)(pc->y-p->start)); + break; + case Jmp: + printf("%2d. jmp %d\n", (int)(pc-p->start), (int)(pc->x-p->start)); + break; + case Char: + printf("%2d. char %c\n", (int)(pc-p->start), pc->c); + break; + case Any: + printf("%2d. any\n", (int)(pc-p->start)); + break; + case Match: + printf("%2d. match\n", (int)(pc-p->start)); + break; + case Save: + printf("%2d. save %d\n", (int)(pc-p->start), pc->n); + } + } +} + +#endif //DEBUG diff --git a/lib/libesp32/re1.5/compilecode.c b/lib/libesp32/re1.5/compilecode.c new file mode 100644 index 000000000..50ee74a13 --- /dev/null +++ b/lib/libesp32/re1.5/compilecode.c @@ -0,0 +1,256 @@ +// Copyright 2014-2019 Paul Sokolovsky. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "re1.5.h" + +#define INSERT_CODE(at, num, pc) \ + ((code ? memmove(code + at + num, code + at, pc - at) : (void)0), pc += num) +#define REL(at, to) (to - at - 2) +#define EMIT(at, byte) (code ? (code[at] = byte) : (void)(at)) +#define PC (prog->bytelen) + +static int _compilecode(const char **re_loc, ByteProg *prog, int sizecode) +{ + const char *re = *re_loc; + char *code = sizecode ? NULL : prog->insts; + int start = PC; + int term = PC; + int alt_label = 0; + + for (; *re && *re != ')'; re++) { + switch (*re) { + case '\\': { + re++; + if (!*re) goto syntax_error; // Trailing backslash + char c = *re | 0x20; + if (c == 'd' || c == 's' || c == 'w') { + term = PC; + EMIT(PC++, NamedClass); + EMIT(PC++, *re); + prog->len++; + break; + } + if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z')) { + goto unsupported_escape; + } + } + default: + term = PC; + EMIT(PC++, Char); + EMIT(PC++, *re); + prog->len++; + break; + case '.': + term = PC; + EMIT(PC++, Any); + prog->len++; + break; + case '[': { + int cnt; + term = PC; + re++; + if (*re == '^') { + EMIT(PC++, ClassNot); + re++; + } else { + EMIT(PC++, Class); + } + PC++; // Skip "# of pairs" byte + prog->len++; + for (cnt = 0; *re != ']'; re++, cnt++) { + if (!*re) goto syntax_error; + if (*re == '\\') { + re++; + if (!*re) goto syntax_error; + if (*re != '\\' && *re != ']') goto unsupported_escape; + } + EMIT(PC++, *re); + if (re[1] == '-' && re[2] != ']') { + re += 2; + } + EMIT(PC++, *re); + } + EMIT(term + 1, cnt); + break; + } + case '(': { + term = PC; + int sub; + int capture = 1; + re++; + if (*re == '?') { + re++; + if (*re == ':') { + capture = 0; + re++; + } else { + *re_loc = re; + return RE1_5_UNSUPPORTED_SYNTAX; + } + } + + if (capture) { + sub = ++prog->sub; + EMIT(PC++, Save); + EMIT(PC++, 2 * sub); + prog->len++; + } + + int res = _compilecode(&re, prog, sizecode); + *re_loc = re; + if (res < 0) return res; + if (*re != ')') return RE1_5_SYNTAX_ERROR; + + if (capture) { + EMIT(PC++, Save); + EMIT(PC++, 2 * sub + 1); + prog->len++; + } + + break; + } + case '{': + *re_loc = re; + return RE1_5_UNSUPPORTED_SYNTAX; + case '?': + if (PC == term) goto syntax_error; // nothing to repeat + INSERT_CODE(term, 2, PC); + if (re[1] == '?') { + EMIT(term, RSplit); + re++; + } else { + EMIT(term, Split); + } + EMIT(term + 1, REL(term, PC)); + prog->len++; + term = PC; + break; + case '*': + if (PC == term) goto syntax_error; // nothing to repeat + INSERT_CODE(term, 2, PC); + EMIT(PC, Jmp); + EMIT(PC + 1, REL(PC, term)); + PC += 2; + if (re[1] == '?') { + EMIT(term, RSplit); + re++; + } else { + EMIT(term, Split); + } + EMIT(term + 1, REL(term, PC)); + prog->len += 2; + term = PC; + break; + case '+': + if (PC == term) goto syntax_error; // nothing to repeat + if (re[1] == '?') { + EMIT(PC, Split); + re++; + } else { + EMIT(PC, RSplit); + } + EMIT(PC + 1, REL(PC, term)); + PC += 2; + prog->len++; + term = PC; + break; + case '|': + if (alt_label) { + EMIT(alt_label, REL(alt_label, PC) + 1); + } + INSERT_CODE(start, 2, PC); + EMIT(PC++, Jmp); + alt_label = PC++; + EMIT(start, Split); + EMIT(start + 1, REL(start, PC)); + prog->len += 2; + term = PC; + break; + case '^': + EMIT(PC++, Bol); + prog->len++; + term = PC; + break; + case '$': + EMIT(PC++, Eol); + prog->len++; + term = PC; + break; + } + } + + if (alt_label) { + EMIT(alt_label, REL(alt_label, PC) + 1); + } + + *re_loc = re; + return RE1_5_SUCCESS; + +syntax_error: + *re_loc = re; + return RE1_5_SYNTAX_ERROR; + +unsupported_escape: + *re_loc = re; + return RE1_5_UNSUPPORTED_ESCAPE; +} + +int re1_5_sizecode(const char *re) +{ + ByteProg dummyprog = { + // Save 0, Save 1, Match; more bytes for "search" (vs "match") prefix code + .bytelen = 5 + NON_ANCHORED_PREFIX + }; + + int res = _compilecode(&re, &dummyprog, /*sizecode*/1); + if (res < 0) return res; + // If unparsed chars left + if (*re) return RE1_5_SYNTAX_ERROR; + + return dummyprog.bytelen; +} + +int re1_5_compilecode(ByteProg *prog, const char *re) +{ + prog->len = 0; + prog->bytelen = 0; + prog->sub = 0; + + // Add code to implement non-anchored operation ("search"). + // For anchored operation ("match"), this code will be just skipped. + // TODO: Implement search in much more efficient manner + prog->insts[prog->bytelen++] = RSplit; + prog->insts[prog->bytelen++] = 3; + prog->insts[prog->bytelen++] = Any; + prog->insts[prog->bytelen++] = Jmp; + prog->insts[prog->bytelen++] = -5; + prog->len += 3; + + prog->insts[prog->bytelen++] = Save; + prog->insts[prog->bytelen++] = 0; + prog->len++; + + int res = _compilecode(&re, prog, /*sizecode*/0); + if (res < 0) return res; + // If unparsed chars left + if (*re) return RE1_5_SYNTAX_ERROR; + + prog->insts[prog->bytelen++] = Save; + prog->insts[prog->bytelen++] = 1; + prog->len++; + + prog->insts[prog->bytelen++] = Match; + prog->len++; + + return RE1_5_SUCCESS; +} + +#if 0 +int main(int argc, char *argv[]) +{ + int pc = 0; + ByteProg *code = re1_5_compilecode(argv[1]); + re1_5_dumpcode(code); +} +#endif diff --git a/lib/libesp32/re1.5/dumpcode.c b/lib/libesp32/re1.5/dumpcode.c new file mode 100644 index 000000000..d7781d849 --- /dev/null +++ b/lib/libesp32/re1.5/dumpcode.c @@ -0,0 +1,65 @@ +// Copyright 2014 Paul Sokolovsky. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "re1.5.h" + +void re1_5_dumpcode(ByteProg *prog) +{ + int pc = 0; + char *code = prog->insts; + while (pc < prog->bytelen) { + printf("%2d: ", pc); + switch(code[pc++]) { + default: + assert(0); +// re1_5_fatal("printprog"); + case Split: + printf("split %d (%d)\n", pc + (signed char)code[pc] + 1, (signed char)code[pc]); + pc++; + break; + case RSplit: + printf("rsplit %d (%d)\n", pc + (signed char)code[pc] + 1, (signed char)code[pc]); + pc++; + break; + case Jmp: + printf("jmp %d (%d)\n", pc + (signed char)code[pc] + 1, (signed char)code[pc]); + pc++; + break; + case Char: + printf("char %c\n", code[pc++]); + break; + case Any: + printf("any\n"); + break; + case Class: + case ClassNot: { + int num = code[pc]; + printf("class%s %d", (code[pc - 1] == ClassNot ? "not" : ""), num); + pc++; + while (num--) { + printf(" 0x%02x-0x%02x", code[pc], code[pc + 1]); + pc += 2; + } + printf("\n"); + break; + } + case NamedClass: + printf("namedclass %c\n", code[pc++]); + break; + case Match: + printf("match\n"); + break; + case Save: + printf("save %d\n", (unsigned char)code[pc++]); + break; + case Bol: + printf("assert bol\n"); + break; + case Eol: + printf("assert eol\n"); + break; + } + } + printf("Bytes: %d, insts: %d\n", prog->bytelen, prog->len); +} diff --git a/lib/libesp32/re1.5/library.json b/lib/libesp32/re1.5/library.json new file mode 100644 index 000000000..8233b2142 --- /dev/null +++ b/lib/libesp32/re1.5/library.json @@ -0,0 +1,13 @@ +{ + "name": "re1.5", + "keywords": "esp32, re", + "description": "Regex", + "version": "0.9", + "repository": + { + "type": "git", + "url": "https://github.com/pfalcon/re1.5" + }, + "frameworks": "*", + "platforms": "*" +} \ No newline at end of file diff --git a/lib/libesp32/re1.5/main.c b/lib/libesp32/re1.5/main.c new file mode 100644 index 000000000..7d688adf1 --- /dev/null +++ b/lib/libesp32/re1.5/main.c @@ -0,0 +1,150 @@ +// Copyright 2007-2009 Russ Cox. All Rights Reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "re1.5.h" + +struct { + char *name; + int (*fn)(ByteProg*, Subject*, const char**, int, int); +} tab[] = { + {"recursive", re1_5_recursiveprog}, + {"recursiveloop", re1_5_recursiveloopprog}, + {"backtrack", re1_5_backtrack}, + {"thompson", re1_5_thompsonvm}, + {"pike", re1_5_pikevm}, +}; + +#ifdef DEBUG +int debug; +#endif +const char *re_engine; + +void +usage(void) +{ + fprintf(stderr, "Usage: re [-hmd] [-e ENGINE] ...\n" + "-h: Print help message and exit\n" + "-m: String is anchored\n" + "-e ENGINE: Specify one of: recursive recursiveloop backtrack thompson pike\n"); +#ifdef DEBUG + fprintf(stderr, + "-d: Print debug messages\n"); +#endif + exit(2); +} + +int +main(int argc, char **argv) +{ + int i, j, k, l; + int is_anchored = 0; + + argv++; + argc--; + while (argc > 0 && argv[0][0] == '-') { + char *arg; + for (arg = &argv[0][1]; *arg; arg++) { + switch (*arg) { + case 'h': + usage(); + break; + case 'm': + is_anchored = 1; + break; +#ifdef DEBUG + case 'd': + debug = 1; + break; +#endif + case 'e': + if (argv[1] == NULL) + re1_5_fatal("-e: Missing Regex engine argument"); + if (re_engine) + re1_5_fatal("-e: Regex engine already specified"); + re_engine = argv[1]; + argv++; + argc--; + break; + default: + re1_5_fatal("Unknown flag"); + } + } + argv++; + argc--; + } + + if(argc < 2) + usage(); + +#ifdef ODEBUG + // Old and unmaintained code + Regexp *re = parse(argv[0]); + printre(re); + printf("\n"); + + Prog *prog = compile(re); + printprog(prog); + printf("=============\n"); +#endif + int sz = re1_5_sizecode(argv[0]); +#ifdef DEBUG + if (debug) printf("Precalculated size: %d\n", sz); +#endif + if (sz == -1) { + re1_5_fatal("Error in regexp"); + } + + ByteProg *code = malloc(sizeof(ByteProg) + sz); + int ret = re1_5_compilecode(code, argv[0]); + if (ret != 0) { + re1_5_fatal("Error in regexp"); + } + + int sub_els = (code->sub + 1) * 2; +#ifdef DEBUG + if (debug) re1_5_dumpcode(code); +#endif + const char *sub[sub_els]; + int engine_found = 0; + for(i=1; i0; k--) + if(sub[k-1]) + break; + for(l=0; l CHAR EOL +%type alt concat repeat single line +%type count + +%% + +line: alt EOL + { + parsed_regexp = $1; + return 1; + } + +alt: + concat +| alt '|' concat + { + $$ = reg(Alt, $1, $3); + } +; + +concat: + repeat +| concat repeat + { + $$ = reg(Cat, $1, $2); + } +; + +repeat: + single +| single '*' + { + $$ = reg(Star, $1, nil); + } +| single '*' '?' + { + $$ = reg(Star, $1, nil); + $$->n = 1; + } +| single '+' + { + $$ = reg(Plus, $1, nil); + } +| single '+' '?' + { + $$ = reg(Plus, $1, nil); + $$->n = 1; + } +| single '?' + { + $$ = reg(Quest, $1, nil); + } +| single '?' '?' + { + $$ = reg(Quest, $1, nil); + $$->n = 1; + } +; + +count: + { + $$ = ++nparen; + } +; + +single: + '(' count alt ')' + { + $$ = reg(Paren, $3, nil); + $$->n = $2; + } +| '(' '?' ':' alt ')' + { + $$ = $4; + } +| CHAR + { + $$ = reg(Lit, nil, nil); + $$->ch = $1; + } +| '.' + { + $$ = reg(Dot, nil, nil); + } +; + +%% + +static char *input; +static Regexp *parsed_regexp; +static int nparen; +int gen; + +static int +yylex(void) +{ + int c; + + if(input == NULL || *input == 0) + return EOL; + c = *input++; + if(strchr("|*+?():.", c)) + return c; + yylval.c = c; + return CHAR; +} + +static void +yyerror(char *s) +{ + re1_5_fatal(s); +} + + +Regexp* +parse(char *s) +{ + Regexp *r, *dotstar; + + input = s; + parsed_regexp = nil; + nparen = 0; + if(yyparse() != 1) + yyerror("did not parse"); + if(parsed_regexp == nil) + yyerror("parser nil"); + + r = reg(Paren, parsed_regexp, nil); // $0 parens + return r; + dotstar = reg(Star, reg(Dot, nil, nil), nil); + dotstar->n = 1; // non-greedy + return reg(Cat, dotstar, r); +} + +Regexp* +reg(int type, Regexp *left, Regexp *right) +{ + Regexp *r; + + r = mal(sizeof *r); + r->type = type; + r->left = left; + r->right = right; + return r; +} + +void +printre(Regexp *r) +{ + switch(r->type) { + default: + printf("???"); + break; + + case Alt: + printf("Alt("); + printre(r->left); + printf(", "); + printre(r->right); + printf(")"); + break; + + case Cat: + printf("Cat("); + printre(r->left); + printf(", "); + printre(r->right); + printf(")"); + break; + + case Lit: + printf("Lit(%c)", r->ch); + break; + + case Dot: + printf("Dot"); + break; + + case Paren: + printf("Paren(%d, ", r->n); + printre(r->left); + printf(")"); + break; + + case Star: + if(r->n) + printf("Ng"); + printf("Star("); + printre(r->left); + printf(")"); + break; + + case Plus: + if(r->n) + printf("Ng"); + printf("Plus("); + printre(r->left); + printf(")"); + break; + + case Quest: + if(r->n) + printf("Ng"); + printf("Quest("); + printre(r->left); + printf(")"); + break; + } +} diff --git a/lib/libesp32/re1.5/pike.c b/lib/libesp32/re1.5/pike.c new file mode 100644 index 000000000..9f060fa11 --- /dev/null +++ b/lib/libesp32/re1.5/pike.c @@ -0,0 +1,176 @@ +// Copyright 2007-2009 Russ Cox. All Rights Reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "re1.5.h" + +typedef struct Thread Thread; +struct Thread +{ + char *pc; + Sub *sub; +}; + +typedef struct ThreadList ThreadList; +struct ThreadList +{ + int n; + Thread t[1]; +}; + +static Thread +thread(char *pc, Sub *sub) +{ + Thread t = {pc, sub}; + return t; +} + +static ThreadList* +threadlist(int n) +{ + return mal(sizeof(ThreadList)+n*sizeof(Thread)); +} + +static void +addthread(ThreadList *l, Thread t, Subject *input, const char *sp) +{ + int off; + if(*t.pc & 0x80) { + decref(t.sub); + return; // already on list + } + *t.pc |= 0x80; + + switch(*t.pc & 0x7f) { + default: + l->t[l->n] = t; + l->n++; + break; + case Jmp: + off = (signed char)t.pc[1]; + t.pc += 2; + addthread(l, thread(t.pc + off, t.sub), input, sp); + break; + case Split: + off = (signed char)t.pc[1]; + t.pc += 2; + addthread(l, thread(t.pc, incref(t.sub)), input, sp); + addthread(l, thread(t.pc + off, t.sub), input, sp); + break; + case RSplit: + off = (signed char)t.pc[1]; + t.pc += 2; + addthread(l, thread(t.pc + off, incref(t.sub)), input, sp); + addthread(l, thread(t.pc, t.sub), input, sp); + break; + case Save: + off = (unsigned char)t.pc[1]; + t.pc += 2; + addthread(l, thread(t.pc, update(t.sub, off, sp)), input, sp); + break; + case Bol: + if(sp == input->begin) + addthread(l, thread(t.pc + 1, t.sub), input, sp); + break; + case Eol: + if(sp == input->end) + addthread(l, thread(t.pc + 1, t.sub), input, sp); + break; + } +} + +int +re1_5_pikevm(ByteProg *prog, Subject *input, const char **subp, int nsubp, int is_anchored) +{ + int i, len; + ThreadList *clist, *nlist, *tmp; + char *pc; + const char *sp; + Sub *sub, *matched; + + matched = nil; + for(i=0; isub[i] = nil; + + len = prog->len; + clist = threadlist(len); + nlist = threadlist(len); + + cleanmarks(prog); + addthread(clist, thread(HANDLE_ANCHORED(prog->insts, is_anchored), sub), input, input->begin); + matched = 0; + for(sp=input->begin;; sp++) { + if(clist->n == 0) + break; + // printf("%d(%02x).", (int)(sp - input->begin), *sp & 0xFF); + cleanmarks(prog); + for(i=0; in; i++) { + pc = clist->t[i].pc; + sub = clist->t[i].sub; + // printf(" %d", (int)(pc - prog->insts)); + if (inst_is_consumer(*pc & 0x7f)) { + // If we need to match a character, but there's none left, + // it's fail (we don't schedule current thread for continuation) + if(sp >= input->end) { + decref(sub); + continue; + } + } + switch(*pc++ & 0x7f) { + case Char: + if(*sp != *pc++) { + decref(sub); + break; + } + case Any: + addthread: + addthread(nlist, thread(pc, sub), input, sp+1); + break; + case Class: + case ClassNot: + if (!_re1_5_classmatch(pc, sp)) { + decref(sub); + break; + } + pc += *(unsigned char*)pc * 2 + 1; + goto addthread; + case NamedClass: + if (!_re1_5_namedclassmatch(pc, sp)) { + decref(sub); + break; + } + pc++; + goto addthread; + case Match: + if(matched) + decref(matched); + matched = sub; + for(i++; i < clist->n; i++) + decref(clist->t[i].sub); + goto BreakFor; + // Jmp, Split, Save handled in addthread, so that + // machine execution matches what a backtracker would do. + // This is discussed (but not shown as code) in + // Regular Expression Matching: the Virtual Machine Approach. + } + } + BreakFor: + // printf("\n"); + tmp = clist; + clist = nlist; + nlist = tmp; + nlist->n = 0; + //if(*sp == '\0') + // break; + } + if(matched) { + for(i=0; isub[i]; + decref(matched); + return 1; + } + return 0; +} diff --git a/lib/libesp32/re1.5/re1.5.h b/lib/libesp32/re1.5/re1.5.h new file mode 100644 index 000000000..a9f255d03 --- /dev/null +++ b/lib/libesp32/re1.5/re1.5.h @@ -0,0 +1,162 @@ +// Copyright 2007-2009 Russ Cox. All Rights Reserved. +// Copyright 2014-2019 Paul Sokolovsky. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#ifndef _RE1_5_REGEXP__H +#define _RE1_5_REGEXP__H + +#include +#include +#include +#include +#include + +#define nil ((void*)0) +#define nelem(x) (sizeof(x)/sizeof((x)[0])) + +typedef struct Regexp Regexp; +typedef struct Prog Prog; +typedef struct ByteProg ByteProg; +typedef struct Inst Inst; +typedef struct Subject Subject; + +struct Regexp +{ + int type; + int n; + int ch; + Regexp *left; + Regexp *right; +}; + +enum /* Regexp.type */ +{ + Alt = 1, + Cat, + Lit, + Dot, + Paren, + Quest, + Star, + Plus, +}; + +Regexp *parse(char*); +Regexp *reg(int type, Regexp *left, Regexp *right); +void printre(Regexp*); +#ifndef re1_5_fatal +void re1_5_fatal(char*); +#endif +#ifndef re1_5_stack_chk +#define re1_5_stack_chk() +#endif +void *mal(int); + +struct Prog +{ + Inst *start; + int len; +}; + +struct ByteProg +{ + int bytelen; + int len; + int sub; + char insts[0]; +}; + +struct Inst +{ + int opcode; + int c; + int n; + Inst *x; + Inst *y; + int gen; // global state, oooh! +}; + +enum /* Inst.opcode */ +{ + // Instructions which consume input bytes (and thus fail if none left) + CONSUMERS = 1, + Char = CONSUMERS, + Any, + Class, + ClassNot, + NamedClass, + + ASSERTS = 0x50, + Bol = ASSERTS, + Eol, + + // Instructions which take relative offset as arg + JUMPS = 0x60, + Jmp = JUMPS, + Split, + RSplit, + + // Other (special) instructions + Save = 0x7e, + Match = 0x7f, +}; + +#define inst_is_consumer(inst) ((inst) < ASSERTS) +#define inst_is_jump(inst) ((inst) & 0x70 == JUMPS) + +Prog *compile(Regexp*); +void printprog(Prog*); + +extern int gen; + +enum { + MAXSUB = 20 +}; + +typedef struct Sub Sub; + +struct Sub +{ + int ref; + int nsub; + const char *sub[MAXSUB]; +}; + +Sub *newsub(int n); +Sub *incref(Sub*); +Sub *copy(Sub*); +Sub *update(Sub*, int, const char*); +void decref(Sub*); + +struct Subject { + const char *begin; + const char *end; +}; + + +#define NON_ANCHORED_PREFIX 5 +#define HANDLE_ANCHORED(bytecode, is_anchored) ((is_anchored) ? (bytecode) + NON_ANCHORED_PREFIX : (bytecode)) + +int re1_5_backtrack(ByteProg*, Subject*, const char**, int, int); +int re1_5_pikevm(ByteProg*, Subject*, const char**, int, int); +int re1_5_recursiveloopprog(ByteProg*, Subject*, const char**, int, int); +int re1_5_recursiveprog(ByteProg*, Subject*, const char**, int, int); +int re1_5_thompsonvm(ByteProg*, Subject*, const char**, int, int); + +// Return codes for re1_5_sizecode() and re1_5_compilecode() +enum { + RE1_5_SUCCESS = 0, + RE1_5_SYNTAX_ERROR = -2, + RE1_5_UNSUPPORTED_ESCAPE = -3, + RE1_5_UNSUPPORTED_SYNTAX = -4, +}; + +int re1_5_sizecode(const char *re); +int re1_5_compilecode(ByteProg *prog, const char *re); +void re1_5_dumpcode(ByteProg *prog); +void cleanmarks(ByteProg *prog); +int _re1_5_classmatch(const char *pc, const char *sp); +int _re1_5_namedclassmatch(const char *pc, const char *sp); + +#endif /*_RE1_5_REGEXP__H*/ diff --git a/lib/libesp32/re1.5/recursive.c b/lib/libesp32/re1.5/recursive.c new file mode 100644 index 000000000..466518ce3 --- /dev/null +++ b/lib/libesp32/re1.5/recursive.c @@ -0,0 +1,79 @@ +// Copyright 2007-2009 Russ Cox. All Rights Reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "re1.5.h" + +static int +recursive(char *pc, const char *sp, Subject *input, const char **subp, int nsubp) +{ + const char *old; + int off; + + if(inst_is_consumer(*pc)) { + // If we need to match a character, but there's none left, it's fail + if(sp >= input->end) + return 0; + } + + re1_5_stack_chk(); + + switch(*pc++) { + case Char: + if(*sp != *pc++) + return 0; + case Any: + return recursive(pc, sp+1, input, subp, nsubp); + case Class: + case ClassNot: + if (!_re1_5_classmatch(pc, sp)) + return 0; + pc += *(unsigned char*)pc * 2 + 1; + return recursive(pc, sp+1, input, subp, nsubp); + case NamedClass: + if (!_re1_5_namedclassmatch(pc, sp)) + return 0; + return recursive(pc+1, sp+1, input, subp, nsubp); + case Match: + return 1; + case Jmp: + off = (signed char)*pc++; + return recursive(pc + off, sp, input, subp, nsubp); + case Split: + off = (signed char)*pc++; + if(recursive(pc, sp, input, subp, nsubp)) + return 1; + return recursive(pc + off, sp, input, subp, nsubp); + case RSplit: + off = (signed char)*pc++; + if(recursive(pc + off, sp, input, subp, nsubp)) + return 1; + return recursive(pc, sp, input, subp, nsubp); + case Save: + off = (unsigned char)*pc++; + if(off >= nsubp) + return recursive(pc, sp, input, subp, nsubp); + old = subp[off]; + subp[off] = sp; + if(recursive(pc, sp, input, subp, nsubp)) + return 1; + subp[off] = old; + return 0; + case Bol: + if(sp != input->begin) + return 0; + return recursive(pc, sp, input, subp, nsubp); + case Eol: + if(sp != input->end) + return 0; + return recursive(pc, sp, input, subp, nsubp); + } + re1_5_fatal("recursive"); + return -1; +} + +int +re1_5_recursiveprog(ByteProg *prog, Subject *input, const char **subp, int nsubp, int is_anchored) +{ + return recursive(HANDLE_ANCHORED(prog->insts, is_anchored), input->begin, input, subp, nsubp); +} diff --git a/lib/libesp32/re1.5/recursiveloop.c b/lib/libesp32/re1.5/recursiveloop.c new file mode 100644 index 000000000..bb337decf --- /dev/null +++ b/lib/libesp32/re1.5/recursiveloop.c @@ -0,0 +1,86 @@ +// Copyright 2007-2009 Russ Cox. All Rights Reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "re1.5.h" + +static int +recursiveloop(char *pc, const char *sp, Subject *input, const char **subp, int nsubp) +{ + const char *old; + int off; + + re1_5_stack_chk(); + + for(;;) { + if(inst_is_consumer(*pc)) { + // If we need to match a character, but there's none left, it's fail + if(sp >= input->end) + return 0; + } + switch(*pc++) { + case Char: + if(*sp != *pc++) + return 0; + case Any: + sp++; + continue; + case Class: + case ClassNot: + if (!_re1_5_classmatch(pc, sp)) + return 0; + pc += *(unsigned char*)pc * 2 + 1; + sp++; + continue; + case NamedClass: + if (!_re1_5_namedclassmatch(pc, sp)) + return 0; + pc++; + sp++; + continue; + case Match: + return 1; + case Jmp: + off = (signed char)*pc++; + pc = pc + off; + continue; + case Split: + off = (signed char)*pc++; + if(recursiveloop(pc, sp, input, subp, nsubp)) + return 1; + pc = pc + off; + continue; + case RSplit: + off = (signed char)*pc++; + if(recursiveloop(pc + off, sp, input, subp, nsubp)) + return 1; + continue; + case Save: + off = (unsigned char)*pc++; + if(off >= nsubp) { + continue; + } + old = subp[off]; + subp[off] = sp; + if(recursiveloop(pc, sp, input, subp, nsubp)) + return 1; + subp[off] = old; + return 0; + case Bol: + if(sp != input->begin) + return 0; + continue; + case Eol: + if(sp != input->end) + return 0; + continue; + } + re1_5_fatal("recursiveloop"); + } +} + +int +re1_5_recursiveloopprog(ByteProg *prog, Subject *input, const char **subp, int nsubp, int is_anchored) +{ + return recursiveloop(HANDLE_ANCHORED(prog->insts, is_anchored), input->begin, input, subp, nsubp); +} diff --git a/lib/libesp32/re1.5/run-tests b/lib/libesp32/re1.5/run-tests new file mode 100755 index 000000000..af5568658 --- /dev/null +++ b/lib/libesp32/re1.5/run-tests @@ -0,0 +1,164 @@ +#! /usr/bin/env python3 + +RE_EXEC = "./re" + +test_suite = [ + # basics + ("search", r"abc", "abcdef"), + ("search", r"cde", "abcdef"), + ("search", r"abc*", "abdef"), + ("search", r"abc*", "abcccdef"), + ("search", r"abc+", "abdef"), + ("search", r"abc+", "abcccdef"), + + # match + ("match", r"abc", "abcdef"), + ("match", r"abc*", "abdef"), + + # search vs match distinction + ("match", r"a*", "baa"), + ("search", r"a*", "baa"), + + # nested group matching + ("match", r"(([0-9]*)([a-z]*)[0-9]*)", "1234hello567"), + ("match", r"([0-9]*)(([a-z]*)([0-9]*))", "1234hello567"), + + # non-capturing groups + ("match", r"(([0-9]*)(?:[a-z]*)[0-9]*)", "1234hello568"), + ("match", r"(?:[0-9]*)(([a-z]*)(?:[0-9]*))", "1234hello568"), + ("match", r"([0-9]*)(?:([a-z]*)(?:[0-9]*))", "1234hello568"), + ("match", r"(?:)", "1234hello568"), + ("match", r"1?:", "1:"), + + # named character classes + ("match", r"\d+", "123abc456"), + ("match", r"\s+", " \t123abc456"), + ("match", r"\w+", "123abc_456 abc"), + ("match", r"(\w+)\s+(\w+)", "ABC \t123hello456 abc"), + ("match", r"(\S+)\s+(\D+)", "ABC \thello abc456 abc"), + ("match", r"(([0-9]*)([a-z]*)\d*)", "123hello456"), + + # classes + ("match", r"[a]*", "a"), + ("search", r"([yab]*)(e*)([cd])", "xyac"), + ("search", r"([yab]*)(e*)([^y]?)$", "xyac"), + ("match", r"[-]*", "--"), + ("match", r"[-a]*", "-a-b"), + ("match", r"[-ab]*", "-a-b"), + ("match", r"[-a-c]*", "-a-b-d-"), + ("match", r"[a-]*", "-a-b"), + ("match", r"[ab-]*", "-a-b"), + ("match", r"[a-c-]*", "-a-b-d-"), + + # escaped metacharacters + ("match", r"(\?:)", ":"), + ("match", r"\(?:", "(:"), + + # non-greedy + ("match", r"a(b??)(b*)c", "abbc"), + ("match", r"a(b+?)(b*)c", "abbbc"), + ("match", r"a(b*?)(b*)c", "abbbbc"), + + # greedy + ("match", r"a(b?)(b*)c", "abbc"), + ("match", r"a(b+)(b*)c", "abbbc"), + ("match", r"a(b*)(b*)c", "abbbbc"), + + # errors + ("search", r"?", ""), + ("search", r"*", ""), + ("search", r"+", ""), + ("search", r"[", ""), + ("search", r"(", ""), + ("search", r")", ""), + ("search", "\\", ""), + ("search", "|+", ""), + ("search", "|*", ""), + ("search", "|?", ""), + ("search", "^*", ""), + ("search", "$*", ""), + ("search", "a*+", ""), + ("search", "a*?", ""), + ("search", "a**", ""), +] + +import re +import sre_constants +import subprocess +from collections import OrderedDict + +def parse_result(string, res): + name, rest = res.split(b" ", 1) + if rest == b"-no match-": + return name, None + if rest == b"REGEX ERROR": + return name, rest + assert rest.startswith(b"match ") + rest = rest[6:] + tuples = [eval(t) for t in rest.split()] + matches = tuple(string[t[0]:t[1]] for t in tuples) + return name, matches + +def fit_str(string, width): + if len(string) <= width: + return string + else: + return string[:width - 2] + ".." + +def main(): + engine_stats = OrderedDict() + for kind, regex, string in test_suite: + # run Python re to get correct result + try: + if kind == "match": + py_res = re.match(regex, string) + else: + py_res = re.search(regex, string) + if py_res is not None: + py_res = (py_res.group(0),) + py_res.groups() + except sre_constants.error: + py_res = b"REGEX ERROR" + + # run our code + try: + args = (["-m"] if kind == "match" else []) + [regex, string] + re_res = subprocess.check_output([RE_EXEC]+args, stderr=subprocess.STDOUT) + re_res = re_res.split(b'\n')[1:-1] # split lines, remove first and last + except subprocess.CalledProcessError as e: + if e.returncode == 2 and e.output == b"fatal error: Error in regexp\n": + re_res = [b"recursive REGEX ERROR", b"recursiveloop REGEX ERROR", b"backtrack REGEX ERROR", b"thompson REGEX ERROR", b"pike REGEX ERROR"] + else: + raise + + # check result of each engine + for engine in re_res: + engine_name, re_res = parse_result(string, engine) + try: + stats = engine_stats[engine_name] + except KeyError: + engine_stats[engine_name] = stats = [0, 0] + + # Thompson algo offers just boolean match/no match status + py_res_cur = py_res + re_res_cur = re_res + if engine_name == b"thompson": + if py_res is not None: + py_res_cur = True + if re_res is not None: + re_res_cur = True + + if py_res_cur == re_res_cur: + print("pass ", end="") + stats[0] += 1 + else: + print("FAIL ", end="") + stats[1] += 1 + + print("%s %-25s %-20s" % (kind[0], fit_str(regex, 25), fit_str(string, 20))) + + print("Ran %d tests, results:" % len(test_suite)) + for name, stats in engine_stats.items(): + print("%15s %2d pass %2d fail" % (str(name, encoding='utf8'), stats[0], stats[1])) + +if __name__ == "__main__": + main() diff --git a/lib/libesp32/re1.5/sub.c b/lib/libesp32/re1.5/sub.c new file mode 100644 index 000000000..7402b1175 --- /dev/null +++ b/lib/libesp32/re1.5/sub.c @@ -0,0 +1,55 @@ +// Copyright 2007-2009 Russ Cox. All Rights Reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "re1.5.h" + +Sub *freesub; + +Sub* +newsub(int n) +{ + Sub *s; + + s = freesub; + if(s != nil) + freesub = (Sub*)s->sub[0]; + else + s = mal(sizeof *s); + s->nsub = n; + s->ref = 1; + return s; +} + +Sub* +incref(Sub *s) +{ + s->ref++; + return s; +} + +Sub* +update(Sub *s, int i, const char *p) +{ + Sub *s1; + int j; + + if(s->ref > 1) { + s1 = newsub(s->nsub); + for(j=0; jnsub; j++) + s1->sub[j] = s->sub[j]; + s->ref--; + s = s1; + } + s->sub[i] = p; + return s; +} + +void +decref(Sub *s) +{ + if(--s->ref == 0) { + s->sub[0] = (char*)freesub; + freesub = s; + } +} diff --git a/lib/libesp32/re1.5/thompson.c b/lib/libesp32/re1.5/thompson.c new file mode 100644 index 000000000..ef2051b0e --- /dev/null +++ b/lib/libesp32/re1.5/thompson.c @@ -0,0 +1,152 @@ +// Copyright 2007-2009 Russ Cox. All Rights Reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "re1.5.h" + +typedef struct Thread Thread; +struct Thread +{ + char *pc; +}; + +typedef struct ThreadList ThreadList; +struct ThreadList +{ + int n; + Thread t[1]; +}; + +static Thread +thread(char *pc) +{ + Thread t = {pc}; + return t; +} + +static ThreadList* +threadlist(int n) +{ + return mal(sizeof(ThreadList)+n*sizeof(Thread)); +} + +static void +addthread(ThreadList *l, Thread t, Subject *input, const char *sp) +{ + int off; + if(*t.pc & 0x80) + return; // already on list + + *t.pc |= 0x80; + l->t[l->n] = t; + l->n++; + + switch(*t.pc & 0x7f) { + case Jmp: + off = (signed char)t.pc[1]; + t.pc += 2; + addthread(l, thread(t.pc + off), input, sp); + break; + case Split: + off = (signed char)t.pc[1]; + t.pc += 2; + addthread(l, thread(t.pc), input, sp); + addthread(l, thread(t.pc + off), input, sp); + break; + case RSplit: + off = (signed char)t.pc[1]; + t.pc += 2; + addthread(l, thread(t.pc + off), input, sp); + addthread(l, thread(t.pc), input, sp); + break; + case Save: + off = (unsigned char)t.pc[1]; + t.pc += 2; + addthread(l, thread(t.pc), input, sp); + break; + case Bol: + if(sp == input->begin) + addthread(l, thread(t.pc + 1), input, sp); + break; + case Eol: + if(sp == input->end - 1) + addthread(l, thread(t.pc + 1), input, sp); + break; + } +} + +int +re1_5_thompsonvm(ByteProg *prog, Subject *input, const char **subp, int nsubp, int is_anchored) +{ + int i, len, matched; + ThreadList *clist, *nlist, *tmp; + char *pc; + const char *sp; + + for(i=0; ilen; + clist = threadlist(len); + nlist = threadlist(len); + + if(nsubp >= 1) + subp[0] = input->begin; + cleanmarks(prog); + addthread(clist, thread(HANDLE_ANCHORED(prog->insts, is_anchored)), input, input->begin); + matched = 0; + for(sp=input->begin;; sp++) { + if(clist->n == 0) + break; + // printf("%d(%02x).", (int)(sp - input->begin), *sp & 0xFF); + cleanmarks(prog); + for(i=0; in; i++) { + pc = clist->t[i].pc; + // printf(" %d", (int)(pc - prog->insts)); + if (inst_is_consumer(*pc & 0x7f)) { + // If we need to match a character, but there's none left, + // it's fail (we don't schedule current thread for continuation) + if(sp >= input->end) + continue; + } + switch(*pc++ & 0x7f) { + case Char: + if(*sp != *pc++) + break; + case Any: + addthread: + addthread(nlist, thread(pc), input, sp); + break; + case Class: + case ClassNot: + if (!_re1_5_classmatch(pc, sp)) + break; + pc += *(unsigned char*)pc * 2 + 1; + goto addthread; + case NamedClass: + if (!_re1_5_namedclassmatch(pc, sp)) + break; + pc++; + goto addthread; + case Match: + if(nsubp >= 2) + subp[1] = sp; + matched = 1; + goto BreakFor; + // Jmp, Split, Save handled in addthread, so that + // machine execution matches what a backtracker would do. + // This is discussed (but not shown as code) in + // Regular Expression Matching: the Virtual Machine Approach. + } + } + BreakFor: + // printf("\n"); + tmp = clist; + clist = nlist; + nlist = tmp; + nlist->n = 0; + //if(sp >= input->end) + // break; + } + return matched; +} diff --git a/lib/libesp32/re1.5/util.c b/lib/libesp32/re1.5/util.c new file mode 100644 index 000000000..5b72b662a --- /dev/null +++ b/lib/libesp32/re1.5/util.c @@ -0,0 +1,24 @@ +// Copyright 2007-2009 Russ Cox. All Rights Reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "re1.5.h" + +void +re1_5_fatal(char *msg) +{ + fprintf(stderr, "fatal error: %s\n", msg); + exit(2); +} + +void* +mal(int n) +{ + void *v; + + v = malloc(n); + if(v == nil) + re1_5_fatal("out of memory"); + memset(v, 0, n); + return v; +} diff --git a/tasmota/xdrv_52_0_berry_struct.ino b/tasmota/xdrv_52_0_berry_struct.ino index 1c3991b80..61ff080c5 100644 --- a/tasmota/xdrv_52_0_berry_struct.ino +++ b/tasmota/xdrv_52_0_berry_struct.ino @@ -23,6 +23,8 @@ #include #include +#include "re1.5.h" + #define BERRY_CONSOLE_CMD_DELIMITER "\x01" typedef LList_elt log_elt; // store the string after the header to avoid double allocation if we had used char* From ba09129398970fd47733859fa603960ba0618fbc Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Fri, 26 Nov 2021 08:44:37 +0100 Subject: [PATCH 114/185] Berry renumber internal types to allow for extensions --- lib/libesp32/Berry/src/be_gc.h | 2 -- lib/libesp32/Berry/src/be_object.h | 20 ++++++++++++-------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/lib/libesp32/Berry/src/be_gc.h b/lib/libesp32/Berry/src/be_gc.h index e22903ef9..0e0ce9e82 100644 --- a/lib/libesp32/Berry/src/be_gc.h +++ b/lib/libesp32/Berry/src/be_gc.h @@ -10,8 +10,6 @@ #include "be_object.h" -#define BE_GCOBJECT BE_STRING - #define gc_object(o) cast(bgcobject*, o) #define gc_cast(o, t, T) ((o) && (o)->type == (t) ? (T*)(o) : NULL) #define cast_proto(o) gc_cast(o, BE_PROTO, bproto) diff --git a/lib/libesp32/Berry/src/be_object.h b/lib/libesp32/Berry/src/be_object.h index 4c8cbf1ab..e19d766d6 100644 --- a/lib/libesp32/Berry/src/be_object.h +++ b/lib/libesp32/Berry/src/be_object.h @@ -19,14 +19,18 @@ #define BE_COMPTR 5 /* common pointer */ #define BE_INDEX 6 /* index for instance variable, previously BE_INT */ #define BE_FUNCTION 7 -#define BE_STRING 8 /* from this type can be gced, see BE_GCOBJECT */ -#define BE_CLASS 9 -#define BE_INSTANCE 10 -#define BE_PROTO 11 -#define BE_LIST 12 -#define BE_MAP 13 -#define BE_MODULE 14 -#define BE_COMOBJ 15 /* common object */ + +#define BE_GCOBJECT 16 /* from this type can be gced */ + +#define BE_STRING 16 +#define BE_CLASS 17 +#define BE_INSTANCE 18 +#define BE_PROTO 19 +#define BE_LIST 20 +#define BE_MAP 21 +#define BE_MODULE 22 +#define BE_COMOBJ 23 /* common object */ + #define BE_NTVFUNC ((0 << 5) | BE_FUNCTION) #define BE_CLOSURE ((1 << 5) | BE_FUNCTION) #define BE_NTVCLOS ((2 << 5) | BE_FUNCTION) From e55025295f3cbe3e381023873bf5b0b294b97ac3 Mon Sep 17 00:00:00 2001 From: stefanbode Date: Fri, 26 Nov 2021 09:05:01 +0100 Subject: [PATCH 115/185] Change venetian blind tilt behavior at 0% and 100% The original target tilt is maintained for the next operation. Anyhow the shutter stops at end position without any tilt change --- tasmota/xdrv_27_shutter.ino | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index ea98aa625..198fbb9c1 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -480,17 +480,16 @@ void ShutterPowerOff(uint8_t i) Shutter[i].direction = 0; } if (Shutter[i].real_position == Shutter[i].start_position) { - //AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Update target tilt shutter %d from %d to %d"), i+1, Shutter[i].tilt_target_pos , Shutter[i].tilt_real_pos); + //AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Update target tilt shutter %d from %d to %d"), i+1, Shutter[i].tilt_target_pos , Shutter[i].tilt_real_pos); Shutter[i].tilt_target_pos = Shutter[i].tilt_real_pos; } TasmotaGlobal.rules_flag.shutter_moved = 1; switch (Shutter[i].switch_mode) { case SHT_SWITCH: - if ((1 << (Settings->shutter_startrelay[i]-1)) & TasmotaGlobal.power) { - ExecuteCommandPowerShutter(Settings->shutter_startrelay[i], 0, SRC_SHUTTER); - } - if ((1 << (Settings->shutter_startrelay[i])) & TasmotaGlobal.power) { - ExecuteCommandPowerShutter(Settings->shutter_startrelay[i]+1, 0, SRC_SHUTTER); + for (int8_t k=0;k<2;k++) { + if ((1 << (Settings->shutter_startrelay[i]+k-1)) & TasmotaGlobal.power) { + ExecuteCommandPowerShutter(Settings->shutter_startrelay[i]+k, 0, SRC_SHUTTER); + } } break; case SHT_PULSE: @@ -516,11 +515,8 @@ void ShutterPowerOff(uint8_t i) char scmnd[20]; #ifdef SHUTTER_CLEAR_PWM_ONSTOP // free the PWM servo lock on stop. - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_PWM "%d 0" ), i+1); - #else - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_PWM "%d %d" ), i+1,Shutter[i].pwm_value); + analogWrite(Pin(GPIO_PWM1, i), 0); #endif - ExecuteCommand(scmnd, SRC_BUTTON); break; } Settings->save_data = savedata_original; @@ -556,11 +552,9 @@ void ShutterUpdatePosition(void) Settings->shutter_position[i] = ShutterRealToPercentPosition(Shutter[i].real_position, i); Shutter[i].start_position = Shutter[i].real_position; - // manage venetian blinds - Shutter[i].tilt_target_pos = Settings->shutter_position[i] == 0 ? Shutter[i].tilt_config[0] : Shutter[i].tilt_target_pos; - Shutter[i].tilt_target_pos = Settings->shutter_position[i] == 100 ? Shutter[i].tilt_config[1] : Shutter[i].tilt_target_pos; //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Pre: Tilt not match %d -> %d, moving: %d"),Shutter[i].tilt_real_pos,Shutter[i].tilt_target_pos,Shutter[i].tiltmoving); - if (abs(Shutter[i].tilt_real_pos - Shutter[i].tilt_target_pos) > Shutter[i].min_TiltChange && Shutter[i].tiltmoving == 0) { + if (abs(Shutter[i].tilt_real_pos - Shutter[i].tilt_target_pos) > Shutter[i].min_TiltChange && Shutter[i].tiltmoving == 0 + && Settings->shutter_position[i] > 0 && Settings->shutter_position[i] < 100) { AddLog(LOG_LEVEL_INFO, PSTR("SHT: Tilt not match %d -> %d"),Shutter[i].tilt_real_pos,Shutter[i].tilt_target_pos); char databuf[1] = ""; XdrvMailbox.data = databuf; From 52c4d2a1f7959866c30814db7a2a258f8f3efda8 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 26 Nov 2021 11:07:56 +0100 Subject: [PATCH 116/185] Refactoring --- tasmota/xdrv_86_esp32_sonoff_spm.ino | 486 ++++++++++++++------------- 1 file changed, 249 insertions(+), 237 deletions(-) diff --git a/tasmota/xdrv_86_esp32_sonoff_spm.ino b/tasmota/xdrv_86_esp32_sonoff_spm.ino index 99df60cfb..808ada4c8 100644 --- a/tasmota/xdrv_86_esp32_sonoff_spm.ino +++ b/tasmota/xdrv_86_esp32_sonoff_spm.ino @@ -124,17 +124,12 @@ #define SSPM_FUNC_SCAN_RESULT 19 // 0x13 #define SSPM_FUNC_SCAN_DONE 25 // 0x19 -#define SSPM_GPIO_ARM_TX 4 -#define SSPM_GPIO_ARM_RX 16 #define SSPM_GPIO_ARM_RESET 15 -#define SSPM_GPIO_PULSE_OUT 13 -#define SSPM_GPIO_PULSE_IN1 12 -#define SSPM_GPIO_PULSE_IN2 14 -#define SSPM_GPIO_LED_STATUS 32 -#define SSPM_GPIO_LED_ERROR 33 #define SSPM_MODULE_NAME_SIZE 12 +/*********************************************************************************************/ + enum SspmMachineStates { SPM_NONE, // Do nothing SPM_WAIT, // Wait 100ms SPM_RESET, // Toggle ARM reset pin @@ -145,8 +140,7 @@ enum SspmMachineStates { SPM_NONE, // Do nothing SPM_WAIT_FOR_SCAN, // Wait for scan sequence to complete SPM_SCAN_COMPLETE, // Scan complete SPM_GET_ENERGY_TOTALS, // Init available Energy totals registers - SPM_UPDATE_CHANNELS, // Update Energy for powered on channels - SPM_UPDATE_TOTALS // Update Energy totals for powered on channels + SPM_UPDATE_CHANNELS // Update Energy for powered on channels }; #include @@ -165,19 +159,20 @@ typedef struct { uint32_t timeout; power_t old_power; + uint16_t last_totals; uint16_t serial_in_byte_counter; uint16_t expected_bytes; uint8_t module[SSPM_MAX_MODULES][SSPM_MODULE_NAME_SIZE]; uint8_t allow_updates; uint8_t get_energy_relay; + uint8_t get_totals; uint8_t rotate; uint8_t module_max; uint8_t module_selected; uint8_t no_send_key; uint8_t counter; uint8_t command_sequence; - uint8_t loop_step; uint8_t mstate; uint8_t last_button; bool discovery_triggered; @@ -186,6 +181,8 @@ typedef struct { uint8_t *SspmBuffer = nullptr; TSspm *Sspm = nullptr; +/*********************************************************************************************/ + void SSPMSetLock(uint32_t seconds) { Sspm->timeout = seconds * 10; // Decremented every 100mSec Sspm->allow_updates = 0; // Disable requests from 100mSec loop @@ -203,24 +200,6 @@ uint16_t SSPMCalculateCRC(uint8_t *frame, uint32_t num) { return crc ^ 0; } -void SSPMTime(uint8_t *frame) { - /* - 0 1 2 3 4 5 6 - YY YY MM DD HH MM SS - 07 e5 0b 06 0c 39 01 - */ - TIME_T time; - BreakTime(Rtc.utc_time, time); - uint16_t year = time.year + 1970; - frame[0] = year >> 8; - frame[1] = year; - frame[2] = time.month; - frame[3] = time.day_of_month; - frame[4] = time.hour; - frame[5] = time.minute; - frame[6] = time.second; -} - void SSPMSend(uint32_t size) { uint16_t crc = SSPMCalculateCRC(SspmBuffer, size -2); SspmBuffer[size -2] = (uint8_t)(crc >> 8); @@ -231,6 +210,21 @@ void SSPMSend(uint32_t size) { SspmSerial->write(SspmBuffer, size); } +void SSPMSendAck(uint32_t command_sequence) { + /* + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 80 0f 00 01 00 01 3d e6 + Marker |Module id |Ac|Cm|Size |Pl|Ix|Chksm| + */ + SspmBuffer[15] = 0x80; + SspmBuffer[17] = 0x00; + SspmBuffer[18] = 0x01; + SspmBuffer[19] = 0x00; + SspmBuffer[20] = command_sequence; + + SSPMSend(23); +} + void SSPMInitSend(void) { /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @@ -261,34 +255,7 @@ void SSPMSendCmnd(uint32_t command) { SSPMSend(22); } -void SSPMSendInitScan(void) { - /* - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 - AA 55 01 ff ff ff ff ff ff ff ff ff ff ff ff 00 10 00 00 02 cd f0 - Marker |Module id |Ac|Cm|Size |Ix|Chksm| - - Acknowledge: - AA 55 01 ff ff ff ff ff ff ff ff ff ff ff ff 80 10 00 01 00 02 e5 03 - |Ac|Cm|Size |Rt|Ix|Chksm| - */ - SSPMSetLock(30); // Disable requests from 100mSec loop - - memset(SspmBuffer, 0xFF, 15); - SspmBuffer[0] = 0xAA; - SspmBuffer[1] = 0x55; - SspmBuffer[2] = 0x01; - - SspmBuffer[15] = 0; - SspmBuffer[16] = SSPM_FUNC_INIT_SCAN; // 0x10 - SspmBuffer[17] = 0; - SspmBuffer[18] = 0; - Sspm->command_sequence++; - SspmBuffer[19] = Sspm->command_sequence; - - SSPMSend(22); - - AddLog(LOG_LEVEL_DEBUG, PSTR("SPM: Start relay scan...")); -} +/*********************************************************************************************/ void SSPMSendOPS(uint32_t relay_num) { /* @@ -318,6 +285,60 @@ void SSPMSendOPS(uint32_t relay_num) { } +void SSPMSendGetOps(uint32_t module) { + /* + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 + aa 55 01 6b 7e 32 37 39 37 34 13 4b 35 36 37 00 04 00 00 08 c0 0a + Marker |Module id |Ac|Cm|Size |Ix|Chksm| + */ + SSPMInitSend(); + memcpy(SspmBuffer +3, Sspm->module[module], SSPM_MODULE_NAME_SIZE); + SspmBuffer[16] = SSPM_FUNC_GET_OPS; // 0x04 + Sspm->command_sequence++; + SspmBuffer[19] = Sspm->command_sequence; + + SSPMSend(22); +} + +void SSPMSendSetRelay(uint32_t relay, uint32_t state) { + /* + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 + AA 55 01 6b 7e 32 37 39 37 34 13 4b 35 36 37 00 08 00 01 44 08 c0 34 + Marker |Module id |Ac|Cm|Size |Pl|Ix|Chksm| + */ + uint8_t channel = 1 << (relay & 0x03); // Channel relays are bit masked + if (state) { + channel |= (channel << 4); + } + uint8_t module = relay >> 2; + SSPMInitSend(); + memcpy(SspmBuffer +3, Sspm->module[module], SSPM_MODULE_NAME_SIZE); + SspmBuffer[16] = SSPM_FUNC_SET_RELAY; // 0x08 + SspmBuffer[18] = 0x01; + SspmBuffer[19] = channel; + Sspm->command_sequence++; + SspmBuffer[20] = Sspm->command_sequence; + + SSPMSend(23); +} + +void SSPMSendGetModuleState(uint32_t module) { + /* + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 + AA 55 01 8b 34 32 37 39 37 34 13 4b 35 36 37 00 09 00 01 0f 05 b5 de + Marker |Module id |Ac|Cm|Size |Pl|Ix|Chksm| + */ + SSPMInitSend(); + memcpy(SspmBuffer +3, Sspm->module[module], SSPM_MODULE_NAME_SIZE); + SspmBuffer[16] = SSPM_FUNC_GET_MODULE_STATE; // 0x09 + SspmBuffer[18] = 0x01; + SspmBuffer[19] = 0x0F; // State of all four relays + Sspm->command_sequence++; + SspmBuffer[20] = Sspm->command_sequence; + + SSPMSend(23); +} + void SSPMSendScheme(uint32_t relay) { /* Time scheme @@ -368,97 +389,6 @@ void SSPMSendScheme(uint32_t relay) { } -void SSPMSendSetTime(void) { - /* - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 - AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 0c 00 0b 07 e5 0b 06 0c 39 01 00 00 02 00 04 8a 37 - Marker |Module id |Ac|Cm|Size |YY YY MM DD HH MM SS|Ln|St|Tr |Ix|Chksm| - UTC time - Tr = Time zone, [-12,+14], can be a decimal, such as 7.5 - - */ - SSPMInitSend(); - SspmBuffer[16] = SSPM_FUNC_SET_TIME; - SspmBuffer[18] = 0x0B; - SSPMTime(SspmBuffer + 19); - SspmBuffer[26] = 0x00; - SspmBuffer[27] = 0x00; - SspmBuffer[28] = 0x02; - SspmBuffer[29] = 0x00; - Sspm->command_sequence++; - SspmBuffer[30] = Sspm->command_sequence; - - SSPMSend(33); -} - -void SSPMSendIAmHere(uint32_t module) { - /* - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 - AA 55 01 8b 34 32 37 39 37 34 13 4b 35 36 37 00 0d 00 00 17 35 b6 - Marker |Module id |Ac|Cm|Size |Ix|Chksm| - - Response - AA 55 01 8b 34 32 37 39 37 34 13 4b 35 36 37 80 0d 00 01 00 17 48 b5 - Marker |Module id |Ac|Cm|Size |Rs|Ix|Chksm| - */ - - -} - -void SSPMSendSetRelay(uint32_t relay, uint32_t state) { - /* - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 - AA 55 01 6b 7e 32 37 39 37 34 13 4b 35 36 37 00 08 00 01 44 08 c0 34 - Marker |Module id |Ac|Cm|Size |Pl|Ix|Chksm| - */ - uint8_t channel = 1 << (relay & 0x03); // Channel relays are bit masked - if (state) { - channel |= (channel << 4); - } - uint8_t module = relay >> 2; - SSPMInitSend(); - memcpy(SspmBuffer +3, Sspm->module[module], SSPM_MODULE_NAME_SIZE); - SspmBuffer[16] = SSPM_FUNC_SET_RELAY; - SspmBuffer[18] = 0x01; - SspmBuffer[19] = channel; - Sspm->command_sequence++; - SspmBuffer[20] = Sspm->command_sequence; - - SSPMSend(23); -} - -void SSPMSendGetModuleState(uint32_t module) { - /* - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 - AA 55 01 8b 34 32 37 39 37 34 13 4b 35 36 37 00 09 00 01 0f 05 b5 de - Marker |Module id |Ac|Cm|Size |Pl|Ix|Chksm| - */ - SSPMInitSend(); - memcpy(SspmBuffer +3, Sspm->module[module], SSPM_MODULE_NAME_SIZE); - SspmBuffer[16] = SSPM_FUNC_GET_MODULE_STATE; - SspmBuffer[18] = 0x01; - SspmBuffer[19] = 0x0F; // State of all four relays - Sspm->command_sequence++; - SspmBuffer[20] = Sspm->command_sequence; - - SSPMSend(23); -} - -void SSPMSendGetOps(uint32_t module) { - /* - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 - aa 55 01 6b 7e 32 37 39 37 34 13 4b 35 36 37 00 04 00 00 08 c0 0a - Marker |Module id |Ac|Cm|Size |Ix|Chksm| - */ - SSPMInitSend(); - memcpy(SspmBuffer +3, Sspm->module[module], SSPM_MODULE_NAME_SIZE); - SspmBuffer[16] = SSPM_FUNC_GET_OPS; - Sspm->command_sequence++; - SspmBuffer[19] = Sspm->command_sequence; - - SSPMSend(22); -} - void SSPMSendGetScheme(uint32_t module) { /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @@ -467,23 +397,124 @@ void SSPMSendGetScheme(uint32_t module) { */ SSPMInitSend(); memcpy(SspmBuffer +3, Sspm->module[module], SSPM_MODULE_NAME_SIZE); - SspmBuffer[16] = SSPM_FUNC_GET_SCHEME; + SspmBuffer[16] = SSPM_FUNC_GET_SCHEME; // 0x0B Sspm->command_sequence++; SspmBuffer[19] = Sspm->command_sequence; SSPMSend(22); } +void SSPMSendSetTime(void) { + /* + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 0c 00 0b 07 e5 0b 06 0c 39 01 00 00 02 00 04 8a 37 + Marker |Module id |Ac|Cm|Size |YY YY MM DD HH MM SS|Ln|St|Tzone|Ix|Chksm| + UTC time + Tzone = Time zone, [-12,+14], can be a decimal, such as 7.5 + */ + SSPMInitSend(); + SspmBuffer[16] = SSPM_FUNC_SET_TIME; // 0x0C + SspmBuffer[18] = 0x0B; + TIME_T time; + BreakTime(Rtc.utc_time, time); + uint16_t year = time.year + 1970; + SspmBuffer[19] = year >> 8; + SspmBuffer[20] = year; + SspmBuffer[21] = time.month; + SspmBuffer[22] = time.day_of_month; + SspmBuffer[23] = time.hour; + SspmBuffer[24] = time.minute; + SspmBuffer[25] = time.second; + SspmBuffer[26] = 0; + SspmBuffer[27] = 0; + SspmBuffer[28] = 1 + (Rtc.time_timezone / 60); // Not sure why the "1" is needed but it is in my case + SspmBuffer[29] = abs(Rtc.time_timezone % 60); + Sspm->command_sequence++; + SspmBuffer[30] = Sspm->command_sequence; + + SSPMSend(33); +} + +void SSPMSendIAmHere(uint32_t relay) { + /* + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 + AA 55 01 8b 34 32 37 39 37 34 13 4b 35 36 37 00 0d 00 00 17 35 b6 + Marker |Module id |Ac|Cm|Size |Ix|Chksm| + + Response is blink green COMM led on SPM-4Relay + AA 55 01 8b 34 32 37 39 37 34 13 4b 35 36 37 80 0d 00 01 00 17 48 b5 + Marker |Module id |Ac|Cm|Size |Rs|Ix|Chksm| + Rs = Return state + */ + uint8_t module = relay >> 2; + SSPMInitSend(); + memcpy(SspmBuffer +3, Sspm->module[module], SSPM_MODULE_NAME_SIZE); + SspmBuffer[16] = SSPM_FUNC_IAMHERE; // 0x0D + Sspm->command_sequence++; + SspmBuffer[19] = Sspm->command_sequence; + + SSPMSend(22); +} + +void SSPMSendInitScan(void) { + /* + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 + AA 55 01 ff ff ff ff ff ff ff ff ff ff ff ff 00 10 00 00 02 cd f0 + Marker |Module id |Ac|Cm|Size |Ix|Chksm| + + Acknowledge: + AA 55 01 ff ff ff ff ff ff ff ff ff ff ff ff 80 10 00 01 00 02 e5 03 + |Ac|Cm|Size |Rt|Ix|Chksm| + */ + SSPMSetLock(30); // Disable requests from 100mSec loop + + memset(SspmBuffer, 0xFF, 15); + SspmBuffer[0] = 0xAA; + SspmBuffer[1] = 0x55; + SspmBuffer[2] = 0x01; + + SspmBuffer[15] = 0; + SspmBuffer[16] = SSPM_FUNC_INIT_SCAN; // 0x10 + SspmBuffer[17] = 0; + SspmBuffer[18] = 0; + Sspm->command_sequence++; + SspmBuffer[19] = Sspm->command_sequence; + + SSPMSend(22); + + AddLog(LOG_LEVEL_DEBUG, PSTR("SPM: Start relay scan...")); +} + +void SSPMSendGetEnergyTotal(uint32_t relay) { + /* + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 + AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 16 00 0d 6b 7e 32 37 39 37 34 13 4b 35 36 37 01 14 e6 93 + Marker | | |Cm|Size |Module id |Ch|Ix|Chksm| + */ + uint8_t module = relay >> 2; + uint8_t channel = relay & 0x03; // Channel relays are NOT bit masked this time + SSPMInitSend(); + SspmBuffer[16] = SSPM_FUNC_GET_ENERGY_TOTAL; // 0x16 + SspmBuffer[18] = 0x0D; + memcpy(SspmBuffer +19, Sspm->module[module], SSPM_MODULE_NAME_SIZE); + SspmBuffer[31] = channel; + Sspm->command_sequence++; + SspmBuffer[32] = Sspm->command_sequence; + + SSPMSend(35); +} + void SSPMSendGetEnergy(uint32_t relay) { /* relay_num = 1..8 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 18 00 10 6b 7e 32 37 39 37 34 13 4b 35 36 37 01 01 00 3c 2a db d1 + Marker | | |Cm|Size |Module id | |Ch| |Ix|Chksm| */ uint8_t module = relay >> 2; uint8_t channel = 1 << (relay & 0x03); // Channel relays are bit masked SSPMInitSend(); - SspmBuffer[16] = SSPM_FUNC_GET_ENERGY; + SspmBuffer[16] = SSPM_FUNC_GET_ENERGY; // 0x18 SspmBuffer[18] = 0x10; memcpy(SspmBuffer +19, Sspm->module[module], SSPM_MODULE_NAME_SIZE); SspmBuffer[31] = 0x01; @@ -496,58 +527,31 @@ void SSPMSendGetEnergy(uint32_t relay) { SSPMSend(38); } -void SSPMSendGetEnergyTotal(uint32_t relay) { - /* - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 - AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 16 00 0d 6b 7e 32 37 39 37 34 13 4b 35 36 37 01 14 e6 93 - */ - uint8_t module = relay >> 2; - uint8_t channel = relay & 0x03; // Channel relays are NOT bit masked this time - SSPMInitSend(); - SspmBuffer[16] = SSPM_FUNC_GET_ENERGY_TOTAL; - SspmBuffer[18] = 0x0D; - memcpy(SspmBuffer +19, Sspm->module[module], SSPM_MODULE_NAME_SIZE); - SspmBuffer[31] = channel; - Sspm->command_sequence++; - SspmBuffer[32] = Sspm->command_sequence; - - SSPMSend(35); -} - void SSPMSendGetLog(uint32_t relay, uint32_t entries) { /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 1a 00 10 6b 7e 32 37 39 37 34 13 4b 35 36 37 00 00 00 1d 09 8c cd + Marker | | |Cm|Size |Module id |Start|End |Ix|Chksm| + Start = newest log start number (Latest is 0) + End = older log end number (End - Start >= 29 (0x1d)) */ uint8_t module = relay >> 2; + uint32_t startlog = (entries >= 29) ? entries -29 : 0; SSPMInitSend(); - SspmBuffer[16] = SSPM_FUNC_GET_LOG; + SspmBuffer[16] = SSPM_FUNC_GET_LOG; // 0x1A SspmBuffer[18] = 0x10; memcpy(SspmBuffer +19, Sspm->module[module], SSPM_MODULE_NAME_SIZE); - SspmBuffer[31] = 0; - SspmBuffer[32] = 0; - SspmBuffer[33] = 0; - SspmBuffer[34] = entries; // Number of logs + SspmBuffer[31] = startlog >> 8; // MSB start log + SspmBuffer[32] = startlog; // LSB start log + SspmBuffer[33] = entries >> 8; // MSB end log + SspmBuffer[34] = entries; // LSB end log - Number of logs Sspm->command_sequence++; SspmBuffer[35] = Sspm->command_sequence; SSPMSend(38); } -void SSPMSendAck(uint32_t command_sequence) { - /* - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 - AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 80 0f 00 01 00 01 3d e6 - Marker |Module id |Ac|Cm|Size |Pl|Ix|Chksm| - */ - SspmBuffer[15] = 0x80; - SspmBuffer[17] = 0x00; - SspmBuffer[18] = 0x01; - SspmBuffer[19] = 0x00; - SspmBuffer[20] = command_sequence; - - SSPMSend(23); -} +/*********************************************************************************************/ void SSPMHandleReceivedData(void) { uint8_t command = SspmBuffer[16]; @@ -817,8 +821,8 @@ void SSPMHandleReceivedData(void) { 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 13 00 24 6b 7e 32 37 39 37 34 13 4b 35 36 37 04 00 00 00 82 01 00 00 14 00 00 0a 00 f0 00 00 00 0a 11 30 00 00 00 0a 02 8f cd AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 00 13 00 24 8b 34 32 37 39 37 34 13 4b 35 36 37 04 00 00 00 82 01 00 00 14 00 00 0a 00 f0 00 00 00 0a 11 30 00 00 00 0a 02 a0 6f - Marker | |Ac|Cm|Size |Module id |Ch| |Ty| |Max I|Min I|Max U |Min U |Max P |Min P |Ix|Chksm| - | 20A| 0.1A| 240V| 0.1V| 4400W| 0.1W| + Marker | |Ac|Cm|Size |Module id |Ch| |Ty|FwVersio|Max I|Min I|Max U |Min U |Max P |Min P |Ix|Chksm| + |130| 1.0.0| 20A| 0.1A| 240V| 0.1V| 4400W| 0.1W| Ty = Type of sub-device. 130: Four-channel sub-device */ if ((0x24 == Sspm->expected_bytes) && (Sspm->module_max < SSPM_MAX_MODULES)) { @@ -888,6 +892,8 @@ void SSPMSerialInput(void) { } } +/*********************************************************************************************/ + void SSPMInit(void) { if (!ValidTemplate(PSTR("Sonoff SPM (POC1)")) && !ValidTemplate(PSTR("Sonoff SPM (POC2)"))) { return; } @@ -929,7 +935,11 @@ void SSPMInit(void) { Sspm->mstate = SPM_WAIT; // Start init sequence } +/*********************************************************************************************/ + void SSPMEvery100ms(void) { + Sspm->last_totals++; + if (Sspm->no_send_key) { Sspm->no_send_key--; } if (Sspm->timeout) { @@ -984,71 +994,63 @@ void SSPMEvery100ms(void) { case SPM_SCAN_COMPLETE: // Scan sequence finished TasmotaGlobal.discovery_counter = 1; // Force TasDiscovery() - Sspm->get_energy_relay = 1; + Sspm->get_energy_relay = 0; Sspm->allow_updates = 1; // Enable requests from 100mSec loop Sspm->mstate = SPM_GET_ENERGY_TOTALS; break; case SPM_GET_ENERGY_TOTALS: // Retrieve Energy total status from up to 128 relays - if (Sspm->allow_updates && (Sspm->get_energy_relay > 0)) { + if (Sspm->allow_updates) { SSPMSetLock(4); - SSPMSendGetEnergyTotal(Sspm->get_energy_relay -1); + SSPMSendGetEnergyTotal(Sspm->get_energy_relay); Sspm->get_energy_relay++; - if (Sspm->get_energy_relay > TasmotaGlobal.devices_present) { - Sspm->get_energy_relay = 1; + if (Sspm->get_energy_relay >= TasmotaGlobal.devices_present) { + Sspm->get_energy_relay = TasmotaGlobal.devices_present; Sspm->mstate = SPM_UPDATE_CHANNELS; } } break; case SPM_UPDATE_CHANNELS: - // Retrieve Energy status from up to 128 powered on relays - if (Sspm->allow_updates && (Sspm->get_energy_relay > 0)) { - power_t powered_on = TasmotaGlobal.power >> (Sspm->get_energy_relay -1); - if (powered_on &1) { - SSPMSetLock(4); - SSPMSendGetEnergy(Sspm->get_energy_relay -1); - } else { - uint32_t relay_set = (Sspm->get_energy_relay -1) >> 2; - uint32_t relay_num = (Sspm->get_energy_relay -1) &3; - if (Sspm->voltage[relay_set][relay_num]) { - Sspm->voltage[relay_set][relay_num] = 0; - Sspm->current[relay_set][relay_num] = 0; - Sspm->active_power[relay_set][relay_num] = 0; - Sspm->apparent_power[relay_set][relay_num] = 0; - Sspm->reactive_power[relay_set][relay_num] = 0; - Sspm->power_factor[relay_set][relay_num] = 0; + // Retrieve Energy status from up to 128 powered on relays (takes 128 * 2s!!) + if (Sspm->allow_updates) { + Sspm->get_energy_relay++; + if (Sspm->get_energy_relay >= TasmotaGlobal.devices_present) { + Sspm->get_energy_relay = 0; + if (Sspm->last_totals > 1200) { // Get totals every 2 minutes (takes 128 * 0.2s) + Sspm->last_totals = 0; + Sspm->get_totals = 1; + } else { + Sspm->get_totals = 0; } } - Sspm->get_energy_relay++; - if (Sspm->get_energy_relay > TasmotaGlobal.devices_present) { - Sspm->get_energy_relay = 1; - } - Sspm->loop_step++; // Rolls over after 256 so allows for scanning at least all relays twice - if (!Sspm->loop_step) { - Sspm->get_energy_relay = 1; - Sspm->mstate = SPM_UPDATE_TOTALS; - } - } - break; - case SPM_UPDATE_TOTALS: - // Retrieve Energy totals from up to 128 powered on relays - if (Sspm->allow_updates && (Sspm->get_energy_relay > 0)) { - power_t powered_on = TasmotaGlobal.power >> (Sspm->get_energy_relay -1); - // Get energy total only once in any 256 requests to safe comms + power_t powered_on = TasmotaGlobal.power >> Sspm->get_energy_relay; if (powered_on &1) { SSPMSetLock(4); - SSPMSendGetEnergyTotal(Sspm->get_energy_relay -1); - } - Sspm->get_energy_relay++; - if (Sspm->get_energy_relay > TasmotaGlobal.devices_present) { - Sspm->get_energy_relay = 1; - Sspm->mstate = SPM_UPDATE_CHANNELS; + if (Sspm->get_totals) { + SSPMSendGetEnergyTotal(Sspm->get_energy_relay); + } else { + SSPMSendGetEnergy(Sspm->get_energy_relay); + } + } else { + uint32_t module = Sspm->get_energy_relay >> 2; + uint32_t channel = Sspm->get_energy_relay &3; + if (Sspm->voltage[module][channel]) { + Sspm->voltage[module][channel] = 0; + Sspm->current[module][channel] = 0; + Sspm->active_power[module][channel] = 0; + Sspm->apparent_power[module][channel] = 0; + Sspm->reactive_power[module][channel] = 0; + Sspm->power_factor[module][channel] = 0; + } } } break; + } } +/*********************************************************************************************/ + bool SSPMSetDevicePower(void) { power_t new_power = XdrvMailbox.index; if (new_power != Sspm->old_power) { @@ -1064,6 +1066,8 @@ bool SSPMSetDevicePower(void) { return true; } +/*********************************************************************************************/ + bool SSPMButton(void) { bool result = false; uint32_t button = XdrvMailbox.payload; @@ -1075,6 +1079,8 @@ bool SSPMButton(void) { return result; } +/*********************************************************************************************/ + const uint16_t SSPM_SIZE = 128; const char kSSPMEnergyPhases[] PROGMEM = "%*_f
%*_f%*_f%*_f|[%*_f,%*_f,%*_f,%*_f]"; @@ -1178,38 +1184,44 @@ void SSPMEnergyShow(bool json) { \*********************************************************************************************/ const char kSSPMCommands[] PROGMEM = "SSPM|" // Prefix - "Log|Energy|History|Scan" ; + "Log|Energy|History|Scan|IamHere" ; void (* const SSPMCommand[])(void) PROGMEM = { - &CmndSSPMLog, &CmndSSPMEnergy, &CmndSSPMEnergyHistory, &CmndSSPMScan }; + &CmndSSPMLog, &CmndSSPMEnergy, &CmndSSPMEnergyHistory, &CmndSSPMScan, &CmndSSPMIamHere }; void CmndSSPMLog(void) { + // Report 29 log entries if ((XdrvMailbox.index < 1) || (XdrvMailbox.index > TasmotaGlobal.devices_present)) { XdrvMailbox.index = 1; } - XdrvMailbox.payload &= 0x1F; // Max 32 entries + XdrvMailbox.payload &= 0xFFFF; // Max 65000 entries SSPMSendGetLog(XdrvMailbox.index -1, XdrvMailbox.payload +1); - ResponseCmndDone(); } void CmndSSPMEnergy(void) { if ((XdrvMailbox.index < 1) || (XdrvMailbox.index > TasmotaGlobal.devices_present)) { XdrvMailbox.index = 1; } SSPMSendGetEnergy(XdrvMailbox.index -1); - ResponseCmndDone(); } void CmndSSPMEnergyHistory(void) { if ((XdrvMailbox.index < 1) || (XdrvMailbox.index > TasmotaGlobal.devices_present)) { XdrvMailbox.index = 1; } SSPMSendGetEnergyTotal(XdrvMailbox.index -1); - ResponseCmndDone(); } void CmndSSPMScan(void) { + // Start relay module scan taking up to 20 seconds Sspm->mstate = SPM_START_SCAN; ResponseCmndChar(PSTR(D_JSON_STARTED)); } +void CmndSSPMIamHere(void) { + // Blink module COMM led containing relay + if ((XdrvMailbox.payload < 1) || (XdrvMailbox.payload > TasmotaGlobal.devices_present)) { XdrvMailbox.payload = 1; } + SSPMSendIAmHere(XdrvMailbox.payload -1); + ResponseCmndDone(); +} + /*********************************************************************************************\ * Interface \*********************************************************************************************/ From 3fc966511ae038caada3be88b9e5f76e4532936b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 26 Nov 2021 11:20:28 +0100 Subject: [PATCH 117/185] New secret --- .github/workflows/Tasmota_build_devel.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Tasmota_build_devel.yml b/.github/workflows/Tasmota_build_devel.yml index c0b4abd37..b397d99b3 100644 --- a/.github/workflows/Tasmota_build_devel.yml +++ b/.github/workflows/Tasmota_build_devel.yml @@ -1363,7 +1363,7 @@ jobs: - name: Push Firmware files to tmp_copy repo uses: Jason2866/copy_file_to_another_repo_action@main env: - API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }} + API_TOKEN_GITHUB: ${{ secrets.API_ACTIONS_GITHUB }} with: source_file: 'firmware' destination_repo: 'arendst/tmp_copy' @@ -1383,7 +1383,7 @@ jobs: - name: Push trigger.txt to start workflow copy in tmp repo uses: Jason2866/copy_file_to_another_repo_action@main env: - API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }} + API_TOKEN_GITHUB: ${{ secrets.API_ACTIONS_GITHUB }} with: source_file: 'trigger.txt' destination_repo: 'arendst/tmp_copy' From c34656daec845361b579e24264f9c7a1a2b4ed3e Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Fri, 26 Nov 2021 11:41:44 +0100 Subject: [PATCH 118/185] Berry list.keys() --- .../Berry/generate/be_fixed_be_class_list.h | 41 ++++++++++--------- lib/libesp32/Berry/src/be_listlib.c | 15 +++++++ 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_list.h b/lib/libesp32/Berry/generate/be_fixed_be_class_list.h index 300efcce0..2450de9a2 100644 --- a/lib/libesp32/Berry/generate/be_fixed_be_class_list.h +++ b/lib/libesp32/Berry/generate/be_fixed_be_class_list.h @@ -1,32 +1,33 @@ #include "be_constobj.h" static be_define_const_map_slots(be_class_list_map) { - { be_const_key(concat, -1), be_const_func(m_concat) }, - { be_const_key(push, -1), be_const_func(m_push) }, - { be_const_key(insert, 1), be_const_func(m_insert) }, - { be_const_key(find, -1), be_const_func(m_find) }, - { be_const_key(remove, 9), be_const_func(m_remove) }, - { be_const_key(clear, -1), be_const_func(m_clear) }, - { be_const_key(size, -1), be_const_func(m_size) }, - { be_const_key(resize, 13), be_const_func(m_resize) }, - { be_const_key(copy, -1), be_const_func(m_copy) }, - { be_const_key(pop, -1), be_const_func(m_pop) }, - { be_const_key(tostring, 3), be_const_func(m_tostring) }, - { be_const_key(opt_eq, -1), be_const_func(m_equal) }, + { be_const_key(opt_add, -1), be_const_func(m_merge) }, { be_const_key(init, -1), be_const_func(m_init) }, - { be_const_key(dot_p, 17), be_const_var(0) }, + { be_const_key(opt_connect, 11), be_const_func(m_connect) }, + { be_const_key(tostring, 2), be_const_func(m_tostring) }, + { be_const_key(pop, 6), be_const_func(m_pop) }, + { be_const_key(insert, -1), be_const_func(m_insert) }, + { be_const_key(size, -1), be_const_func(m_size) }, + { be_const_key(remove, 12), be_const_func(m_remove) }, + { be_const_key(find, -1), be_const_func(m_find) }, + { be_const_key(push, 1), be_const_func(m_push) }, + { be_const_key(item, 5), be_const_func(m_item) }, + { be_const_key(concat, -1), be_const_func(m_concat) }, + { be_const_key(dot_p, -1), be_const_var(0) }, + { be_const_key(iter, -1), be_const_func(m_iter) }, + { be_const_key(copy, -1), be_const_func(m_copy) }, + { be_const_key(reverse, 13), be_const_func(m_reverse) }, + { be_const_key(keys, -1), be_const_func(m_keys) }, + { be_const_key(resize, 16), be_const_func(m_resize) }, { be_const_key(setitem, -1), be_const_func(m_setitem) }, - { be_const_key(opt_connect, 4), be_const_func(m_connect) }, - { be_const_key(opt_neq, -1), be_const_func(m_nequal) }, - { be_const_key(opt_add, 18), be_const_func(m_merge) }, - { be_const_key(iter, 20), be_const_func(m_iter) }, - { be_const_key(item, -1), be_const_func(m_item) }, - { be_const_key(reverse, -1), be_const_func(m_reverse) }, + { be_const_key(opt_neq, 7), be_const_func(m_nequal) }, + { be_const_key(clear, -1), be_const_func(m_clear) }, + { be_const_key(opt_eq, -1), be_const_func(m_equal) }, }; static be_define_const_map( be_class_list_map, - 21 + 22 ); BE_EXPORT_VARIABLE be_define_const_class( diff --git a/lib/libesp32/Berry/src/be_listlib.c b/lib/libesp32/Berry/src/be_listlib.c index cc8c8d8d4..c63107876 100644 --- a/lib/libesp32/Berry/src/be_listlib.c +++ b/lib/libesp32/Berry/src/be_listlib.c @@ -432,6 +432,19 @@ static int list_equal(bvm *vm, bbool iseq) be_return(vm); } +static int m_keys(bvm *vm) +{ + be_getmember(vm, 1, ".p"); + list_check_data(vm, 1); + int size = be_data_size(vm, -1); + be_getbuiltin(vm, "range"); + be_pushint(vm, 0); + be_pushint(vm, size - 1); + be_call(vm, 2); + be_pop(vm, 2); + be_return(vm); +} + static int m_equal(bvm *vm) { return list_equal(vm, btrue); @@ -463,6 +476,7 @@ void be_load_listlib(bvm *vm) { "concat", m_concat }, { "reverse", m_reverse }, { "copy", m_copy }, + { "keys", m_keys }, { "..", m_connect }, { "+", m_merge }, { "==", m_equal }, @@ -491,6 +505,7 @@ class be_class_list (scope: global, name: list) { concat, func(m_concat) reverse, func(m_reverse) copy, func(m_copy) + keys, func(m_keys) .., func(m_connect) +, func(m_merge) ==, func(m_equal) From 81714141d966f86304e50b1a676ec187f98cff72 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 26 Nov 2021 12:12:58 +0100 Subject: [PATCH 119/185] CI language tests only for ESP82XX builds --- .github/workflows/build_all_the_things.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_all_the_things.yml b/.github/workflows/build_all_the_things.yml index 1f9c6bc24..41629dbab 100644 --- a/.github/workflows/build_all_the_things.yml +++ b/.github/workflows/build_all_the_things.yml @@ -60,7 +60,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - variant: [ tasmota, tasmota32 ] + variant: [ tasmota ] language: [ AF, BG, BR, CN, CZ, DE, ES, FR, FY, GR, HE, HU, IT, KO, NL, PL, PT, RO, RU, SE, SK, TR, TW, UK, VN ] steps: - uses: actions/checkout@v2 From e4721f419e173c40365d40676f416c2d9b48485a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 26 Nov 2021 12:30:59 +0100 Subject: [PATCH 120/185] Back to former working secret --- .github/workflows/Tasmota_build_devel.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Tasmota_build_devel.yml b/.github/workflows/Tasmota_build_devel.yml index b397d99b3..c0b4abd37 100644 --- a/.github/workflows/Tasmota_build_devel.yml +++ b/.github/workflows/Tasmota_build_devel.yml @@ -1363,7 +1363,7 @@ jobs: - name: Push Firmware files to tmp_copy repo uses: Jason2866/copy_file_to_another_repo_action@main env: - API_TOKEN_GITHUB: ${{ secrets.API_ACTIONS_GITHUB }} + API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }} with: source_file: 'firmware' destination_repo: 'arendst/tmp_copy' @@ -1383,7 +1383,7 @@ jobs: - name: Push trigger.txt to start workflow copy in tmp repo uses: Jason2866/copy_file_to_another_repo_action@main env: - API_TOKEN_GITHUB: ${{ secrets.API_ACTIONS_GITHUB }} + API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }} with: source_file: 'trigger.txt' destination_repo: 'arendst/tmp_copy' From 71e4302bece72b880022f902caf771413b9bed51 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 26 Nov 2021 14:25:55 +0100 Subject: [PATCH 121/185] Next secret try --- .github/workflows/Tasmota_build_devel.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Tasmota_build_devel.yml b/.github/workflows/Tasmota_build_devel.yml index c0b4abd37..b397d99b3 100644 --- a/.github/workflows/Tasmota_build_devel.yml +++ b/.github/workflows/Tasmota_build_devel.yml @@ -1363,7 +1363,7 @@ jobs: - name: Push Firmware files to tmp_copy repo uses: Jason2866/copy_file_to_another_repo_action@main env: - API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }} + API_TOKEN_GITHUB: ${{ secrets.API_ACTIONS_GITHUB }} with: source_file: 'firmware' destination_repo: 'arendst/tmp_copy' @@ -1383,7 +1383,7 @@ jobs: - name: Push trigger.txt to start workflow copy in tmp repo uses: Jason2866/copy_file_to_another_repo_action@main env: - API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }} + API_TOKEN_GITHUB: ${{ secrets.API_ACTIONS_GITHUB }} with: source_file: 'trigger.txt' destination_repo: 'arendst/tmp_copy' From cd371fa67236a29ca5b564d97e23c3a2897129b1 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 26 Nov 2021 14:57:29 +0100 Subject: [PATCH 122/185] Try.... --- .github/workflows/Tasmota_build_devel.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Tasmota_build_devel.yml b/.github/workflows/Tasmota_build_devel.yml index b397d99b3..c0b4abd37 100644 --- a/.github/workflows/Tasmota_build_devel.yml +++ b/.github/workflows/Tasmota_build_devel.yml @@ -1363,7 +1363,7 @@ jobs: - name: Push Firmware files to tmp_copy repo uses: Jason2866/copy_file_to_another_repo_action@main env: - API_TOKEN_GITHUB: ${{ secrets.API_ACTIONS_GITHUB }} + API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }} with: source_file: 'firmware' destination_repo: 'arendst/tmp_copy' @@ -1383,7 +1383,7 @@ jobs: - name: Push trigger.txt to start workflow copy in tmp repo uses: Jason2866/copy_file_to_another_repo_action@main env: - API_TOKEN_GITHUB: ${{ secrets.API_ACTIONS_GITHUB }} + API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }} with: source_file: 'trigger.txt' destination_repo: 'arendst/tmp_copy' From 727443e96411ea7fdb9411bb67b9d9f9e9ab849d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 26 Nov 2021 15:40:53 +0100 Subject: [PATCH 123/185] Rename Tasmota_build_development.yml to Tasmota_build_development.yml.off --- ...ta_build_development.yml => Tasmota_build_development.yml.off} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{Tasmota_build_development.yml => Tasmota_build_development.yml.off} (100%) diff --git a/.github/workflows/Tasmota_build_development.yml b/.github/workflows/Tasmota_build_development.yml.off similarity index 100% rename from .github/workflows/Tasmota_build_development.yml rename to .github/workflows/Tasmota_build_development.yml.off From d4e4a2ecd7a3c3ff71dfa4045938ad526dc5732f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 26 Nov 2021 15:42:12 +0100 Subject: [PATCH 124/185] Activate new firmware file transfer --- .github/workflows/Tasmota_build_devel.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Tasmota_build_devel.yml b/.github/workflows/Tasmota_build_devel.yml index c0b4abd37..fe3f995d1 100644 --- a/.github/workflows/Tasmota_build_devel.yml +++ b/.github/workflows/Tasmota_build_devel.yml @@ -3,7 +3,7 @@ name: Build_firmware_development_cache on: workflow_dispatch: # Manually start a workflow push: - branches: development-off + branches: development paths-ignore: - '.github/**' # Ignore changes towards the .github directory - '**.md' # Do no build if *.md files changes From f336964cd3139d74a74582c804524d064db510fb Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 26 Nov 2021 17:41:45 +0100 Subject: [PATCH 125/185] add #define USE_WEBCLIENT_HTTPS for some env --- tasmota/tasmota_configurations_ESP32.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tasmota/tasmota_configurations_ESP32.h b/tasmota/tasmota_configurations_ESP32.h index b358d74e0..74ed07d32 100644 --- a/tasmota/tasmota_configurations_ESP32.h +++ b/tasmota/tasmota_configurations_ESP32.h @@ -73,6 +73,8 @@ #define USE_ODROID_GO // Add support for Odroid Go #define USE_SDCARD +#define USE_WEBCLIENT_HTTPS + #undef USE_HOME_ASSISTANT #define USE_I2C @@ -113,6 +115,8 @@ #define USE_I2S_WEBRADIO #define USE_SDCARD +#define USE_WEBCLIENT_HTTPS + #define USE_I2C #define USE_BMA423 #define USE_MPU_ACCEL @@ -200,6 +204,8 @@ #undef USE_DOMOTICZ #undef USE_HOME_ASSISTANT +#define USE_WEBCLIENT_HTTPS + #define USE_I2S #define USE_SPI #define USE_LVGL From d4bbbc6f801a752d0e2428c042874a84a78deb7a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 26 Nov 2021 17:50:50 +0100 Subject: [PATCH 126/185] USE_AUTOCONF for lvgl env --- platformio_tasmota_env32.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio_tasmota_env32.ini b/platformio_tasmota_env32.ini index b67f4c90a..380fac213 100644 --- a/platformio_tasmota_env32.ini +++ b/platformio_tasmota_env32.ini @@ -81,7 +81,7 @@ lib_extra_dirs = lib/libesp32, lib/lib_basic, lib/lib_display [env:tasmota32-lvgl] extends = env:tasmota32_base -build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_LVGL +build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_LVGL -DUSE_AUTOCONF board_build.f_cpu = 160000000L lib_extra_dirs = lib/libesp32, lib/libesp32_lvgl, lib/lib_basic, lib/lib_i2c, lib/lib_rf, lib/lib_div, lib/lib_ssl, lib/lib_display From 00b0ae245a6dc720babfeca1a617ad5ea582f5f9 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Fri, 26 Nov 2021 18:58:35 +0100 Subject: [PATCH 127/185] Add HTTPS support to ``WebQuery`` (ESP32x only) --- CHANGELOG.md | 1 + tasmota/xdrv_01_webserver.ino | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b2373fbe..c3b35f9f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ All notable changes to this project will be documented in this file. - Command ``IfxPeriod `` to overrule ``Teleperiod`` for Influx messages (#13750) - OTA over HTTPS (ESP32x only) - Berry add ``import re`` regex module +- Add HTTPS support to ``WebQuery`` (ESP32x only) ### Changed - ESP8266 Gratuitous ARP enabled and set to 60 seconds (#13623) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index cab94ba46..ec28f4f23 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -3117,8 +3117,12 @@ int WebQuery(char *buffer) // An unlimited number of headers can be sent per request, and a body can be sent for all command types // The body will be ignored if sending a GET command +#if defined(ESP32) && defined(USE_WEBCLIENT_HTTPS) + HTTPClientLight http; +#else // HTTP only WiFiClient http_client; HTTPClient http; +#endif int status = WEBCMND_WRONG_PARAMETERS; @@ -3127,7 +3131,11 @@ int WebQuery(char *buffer) char *method = strtok_r(temp, " ", &temp); if (url && method) { +#if defined(ESP32) && defined(USE_WEBCLIENT_HTTPS) + if (http.begin(UrlEncode(url))) { +#else // HTTP only if (http.begin(http_client, UrlEncode(url))) { +#endif char empty_body[1] = { 0 }; char *body = empty_body; if (temp) { // There is a body and/or header @@ -3204,9 +3212,15 @@ int WebGetConfig(char *buffer) DEBUG_CORE_LOG(PSTR("WEB: Config Uri '%s'"), url.c_str()); + +#if defined(ESP32) && defined(USE_WEBCLIENT_HTTPS) + HTTPClientLight http; + if (http.begin(UrlEncode(url))) { // UrlEncode(url) = |http://192.168.178.86/cm?cmnd=POWER1%20ON| +#else // HTTP only WiFiClient http_client; HTTPClient http; if (http.begin(http_client, UrlEncode(url))) { // UrlEncode(url) = |http://192.168.178.86/cm?cmnd=POWER1%20ON| +#endif int http_code = http.GET(); // Start connection and send HTTP header if (http_code > 0) { // http_code will be negative on error status = WEBCMND_DONE; From 7808a58ffa8015c81bd2ff257da736ad2c57717e Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Fri, 26 Nov 2021 19:03:21 +0100 Subject: [PATCH 128/185] Berry improved re.split --- lib/libesp32/Berry/default/be_re_lib.c | 88 ++++++++++++++++++-------- 1 file changed, 62 insertions(+), 26 deletions(-) diff --git a/lib/libesp32/Berry/default/be_re_lib.c b/lib/libesp32/Berry/default/be_re_lib.c index 2c94c3440..bc28c0e67 100644 --- a/lib/libesp32/Berry/default/be_re_lib.c +++ b/lib/libesp32/Berry/default/be_re_lib.c @@ -26,6 +26,7 @@ re = module("re") re.compile = def (regex_str) end # native re.match = def (regex_str, str) end # native re.search = def (regex_str, str) end # native +re.split = def (regex_str, str) end # native *******************************************************************/ @@ -145,39 +146,73 @@ int re_pattern_match(bvm *vm) { be_raise(vm, "type_error", NULL); } -// Berry: `re_pattern.split(s:string) -> list(string)` + +int re_pattern_split_run(bvm *vm, ByteProg *code, const char *hay, int split_limit) { + Subject subj = {hay, hay + strlen(hay)}; + + int sub_els = (code->sub + 1) * 2; + const char *sub[sub_els]; + + be_newobject(vm, "list"); + while (1) { + if (split_limit == 0 || !re1_5_recursiveloopprog(code, &subj, sub, sub_els, bfalse)) { + be_pushnstring(vm, subj.begin, subj.end - subj.begin); + be_data_push(vm, -2); + be_pop(vm, 1); + break; + } + + if (sub[0] == NULL || sub[1] == NULL || sub[0] == sub[1]) { + be_raise(vm, "internal_error", "can't match"); + } + be_pushnstring(vm, subj.begin, sub[0] - subj.begin); + be_data_push(vm, -2); + be_pop(vm, 1); + subj.begin = sub[1]; + split_limit--; + } + be_pop(vm, 1); // remove list + be_return(vm); // return list object +} + +// Berry: `re_pattern.split(s:string [, split_limit:int]) -> list(string)` int re_pattern_split(bvm *vm) { int32_t argc = be_top(vm); // Get the number of arguments if (argc >= 2 && be_isstring(vm, 2)) { + int split_limit = -1; + if (argc >= 3) { + split_limit = be_toint(vm, 3); + } const char * hay = be_tostring(vm, 2); be_getmember(vm, 1, "_p"); ByteProg * code = (ByteProg*) be_tocomptr(vm, -1); - - Subject subj = {hay, hay + strlen(hay)}; - int sub_els = (code->sub + 1) * 2; - const char *sub[sub_els]; + return re_pattern_split_run(vm, code, hay, split_limit); + } + be_raise(vm, "type_error", NULL); +} - be_newobject(vm, "list"); - while (1) { - if (!re1_5_recursiveloopprog(code, &subj, sub, sub_els, bfalse)) { - be_pushnstring(vm, subj.begin, subj.end - subj.begin); - be_data_push(vm, -2); - be_pop(vm, 1); - break; - } - - if (sub[0] == NULL || sub[1] == NULL || sub[0] == sub[1]) { - be_raise(vm, "internal_error", "can't match"); - } - be_pushnstring(vm, subj.begin, sub[0] - subj.begin); - be_data_push(vm, -2); - be_pop(vm, 1); - subj.begin = sub[1]; +// Berry: `re.split(pattern:string, s:string [, split_limit:int]) -> list(string)` +int be_re_split(bvm *vm) { + int32_t argc = be_top(vm); // Get the number of arguments + if (argc >= 2 && be_isstring(vm, 1) && be_isstring(vm, 2)) { + const char * regex_str = be_tostring(vm, 1); + const char * hay = be_tostring(vm, 2); + int split_limit = -1; + if (argc >= 3) { + split_limit = be_toint(vm, 3); } - be_pop(vm, 1); // remove list - be_return(vm); // return list object + int sz = re1_5_sizecode(regex_str); + if (sz < 0) { + be_raise(vm, "internal_error", "error in regex"); + } + ByteProg *code = be_os_malloc(sizeof(ByteProg) + sz); + int ret = re1_5_compilecode(code, regex_str); + if (ret != 0) { + be_raise(vm, "internal_error", "error in regex"); + } + return re_pattern_split_run(vm, code, hay, split_limit); } be_raise(vm, "type_error", NULL); } @@ -187,11 +222,12 @@ int re_pattern_split(bvm *vm) { ********************************************************************/ be_local_module(re, "re", - be_nested_map(3, + be_nested_map(4, ( (struct bmapnode*) &(const bmapnode[]) { { be_nested_key("compile", 1000265118, 7, -1), be_const_func(be_re_compile) }, - { be_nested_key("search", -2144130903, 6, 2), be_const_func(be_re_search) }, - { be_nested_key("match", 2116038550, 5, -1), be_const_func(be_re_match) }, + { be_nested_key("search", -2144130903, 6, -1), be_const_func(be_re_search) }, + { be_nested_key("match", 2116038550, 5, 0), be_const_func(be_re_match) }, + { be_nested_key("split", -2017972765, 5, -1), be_const_func(be_re_split) }, })) ); BE_EXPORT_VARIABLE be_define_const_native_module(re); From ba4b98f773232190f20ac1242990b4301c9e328f Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Fri, 26 Nov 2021 20:56:40 +0100 Subject: [PATCH 129/185] Berry list.concat takes a delimiter --- lib/libesp32/Berry/src/be_listlib.c | 30 ++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/lib/libesp32/Berry/src/be_listlib.c b/lib/libesp32/Berry/src/be_listlib.c index c63107876..aa64ad018 100644 --- a/lib/libesp32/Berry/src/be_listlib.c +++ b/lib/libesp32/Berry/src/be_listlib.c @@ -333,18 +333,28 @@ static int m_merge(bvm *vm) be_return(vm); /* return self */ } -static void connect(bvm *vm, bvalue *begin, bvalue *end) +static void connect(bvm *vm, bvalue *begin, bvalue *end, const char * delimiter) { size_t l0 = be_strlen(vm, -1), len = l0; + size_t d = delimiter ? strlen(delimiter) : 0; /* len of delimiter */ + bbool non_empty = l0 > 0; /* is the string non-empty, i.e. needs a prefix delimiter */ char *buf, *p; bvalue *it; for (it = begin; it < end; ++it) { - len += str_len(var_tostr(it)); + len += str_len(var_tostr(it)) + d; + } + if (!non_empty) { + len -= d; /* remove size for first delimiter non needed */ } buf = be_pushbuffer(vm, len); memcpy(buf, be_tostring(vm, -2), l0); p = buf + l0; for (it = begin; it < end; ++it) { + if ((it != begin || non_empty) && delimiter) { + /* add delimiter */ + memcpy(p, delimiter, d); + p += d; + } bstring *s = var_tostr(it); size_t l = str_len(s); memcpy(p, str(s), l); @@ -355,15 +365,20 @@ static void connect(bvm *vm, bvalue *begin, bvalue *end) be_pop(vm, 2); } -static void list_concat(bvm *vm, blist *list) +static void list_concat(bvm *vm, blist *list, const char * delimiter) { bvalue *it, *begin = be_list_data(list); bvalue *end = be_list_end(list); be_pushstring(vm, ""); /* push a empty string */ for (it = begin; it < end;) { for (; it < end && var_isstr(it); ++it); - connect(vm, begin, it); /* connect string list */ + connect(vm, begin, it, delimiter); /* connect string list */ if (it < end) { + if (delimiter && be_strlen(vm, -1) > 0) { + be_pushstring(vm, delimiter); + be_strconcat(vm, -2); + be_pop(vm, 1); + } /* connect other value */ var_setval(vm->top, it); be_incrtop(vm); @@ -378,10 +393,15 @@ static void list_concat(bvm *vm, blist *list) static int m_concat(bvm *vm) { bvalue *value; + int top = be_top(vm); be_getmember(vm, 1, ".p"); list_check_data(vm, 1); value = be_indexof(vm, -1); - list_concat(vm, var_toobj(value)); + const char * delimiter = NULL; + if (top >= 2) { + delimiter = be_tostring(vm, 2); + } + list_concat(vm, var_toobj(value), delimiter); be_return(vm); } From 71fb9b4dfc41d67c29c22a2489c238c18fdc5dec Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Fri, 26 Nov 2021 16:42:24 -0600 Subject: [PATCH 130/185] Fix next check time tests, mcast 2 times, only send ann if all acks rcvd --- tasmota/support_device_groups.ino | 67 +++++++++++++++++++------------ 1 file changed, 41 insertions(+), 26 deletions(-) diff --git a/tasmota/support_device_groups.ino b/tasmota/support_device_groups.ino index cd628522e..2f2089a12 100644 --- a/tasmota/support_device_groups.ino +++ b/tasmota/support_device_groups.ino @@ -24,9 +24,11 @@ #ifdef USE_DEVICE_GROUPS //#define DEVICE_GROUPS_DEBUG -#define DGR_MEMBER_TIMEOUT 45000 -#define DGR_ANNOUNCEMENT_INTERVAL 60000 -#define DEVICE_GROUP_MESSAGE "TASMOTA_DGR" +#define DGR_MULTICAST_REPEAT_COUNT 1 // Number of times to re-send each multicast +#define DGR_ACK_WAIT_TIME 150 // Initial ms to wait for ack's +#define DGR_MEMBER_TIMEOUT 45000 // ms to wait for ack's before removing a member +#define DGR_ANNOUNCEMENT_INTERVAL 60000 // ms between announcements +#define DEVICE_GROUP_MESSAGE "TASMOTA_DGR" const char kDeviceGroupMessage[] PROGMEM = DEVICE_GROUP_MESSAGE; @@ -49,6 +51,7 @@ struct device_group { uint16_t ack_check_interval; uint8_t message_header_length; uint8_t initial_status_requests_remaining; + uint8_t multicasts_remaining; char group_name[TOPSZ]; uint8_t message[128]; struct device_group_member * device_group_members; @@ -815,6 +818,7 @@ bool _SendDeviceGroupMessage(int32_t device, DevGroupMessageType message_type, . } // Multicast the packet. + device_group->multicasts_remaining = DGR_MULTICAST_REPEAT_COUNT; SendReceiveDeviceGroupMessage(device_group, nullptr, device_group->message, device_group->message_length, false); #ifdef USE_DEVICE_GROUPS_SEND @@ -832,14 +836,14 @@ bool _SendDeviceGroupMessage(int32_t device, DevGroupMessageType message_type, . device_group->next_ack_check_time = 0; } else { - device_group->ack_check_interval = 200; + device_group->ack_check_interval = DGR_ACK_WAIT_TIME; device_group->next_ack_check_time = now + device_group->ack_check_interval; - if (device_group->next_ack_check_time < next_check_time) next_check_time = device_group->next_ack_check_time; + if ((int32_t)(next_check_time - device_group->next_ack_check_time) > 0) next_check_time = device_group->next_ack_check_time; device_group->member_timeout_time = now + DGR_MEMBER_TIMEOUT; } device_group->next_announcement_time = now + DGR_ANNOUNCEMENT_INTERVAL; - if (device_group->next_announcement_time < next_check_time) next_check_time = device_group->next_announcement_time; + if ((int32_t)(next_check_time - device_group->next_announcement_time) > 0) next_check_time = device_group->next_announcement_time; return 0; } @@ -868,6 +872,8 @@ void ProcessDeviceGroupMessage(uint8_t * message, int message_length) return; } device_group_member->ip_address = remote_ip; + device_group_member->acked_sequence = device_group->outgoing_sequence; + device_group->member_timeout_time = millis() + DGR_MEMBER_TIMEOUT; *flink = device_group_member; AddLog(LOG_LEVEL_DEBUG, PSTR("DGR: Member %s added"), IPAddressToString(remote_ip)); break; @@ -914,7 +920,7 @@ void DeviceGroupsLoop(void) uint32_t now = millis(); // If it's time to check on things, iterate through the device groups. - if ((long)(now - next_check_time) >= 0) { + if ((int32_t)(now - next_check_time) >= 0) { #ifdef DEVICE_GROUPS_DEBUG AddLog(LOG_LEVEL_DEBUG, PSTR("DGR: Checking next_check_time=%u, now=%u"), next_check_time, now); #endif // DEVICE_GROUPS_DEBUG @@ -927,7 +933,7 @@ AddLog(LOG_LEVEL_DEBUG, PSTR("DGR: Checking next_check_time=%u, now=%u"), next_c if (device_group->next_ack_check_time) { // If it's time to check for acks, ... - if ((long)(now - device_group->next_ack_check_time) >= 0) { + if ((int32_t)(now - device_group->next_ack_check_time) >= 0) { // If we're still sending the initial status request message, send it. if (device_group->initial_status_requests_remaining) { @@ -951,7 +957,7 @@ AddLog(LOG_LEVEL_DEBUG, PSTR("DGR: Checking next_check_time=%u, now=%u"), next_c // If we're done initializing, iterate through the group memebers, ... else { #ifdef DEVICE_GROUPS_DEBUG - AddLog(LOG_LEVEL_DEBUG, PSTR("DGR: Checking for ack's")); + AddLog(LOG_LEVEL_DEBUG, PSTR("DGR: Checking for %s ack's"), device_group->group_name); #endif // DEVICE_GROUPS_DEBUG bool acked = true; struct device_group_member ** flink = &device_group->device_group_members; @@ -963,17 +969,23 @@ AddLog(LOG_LEVEL_DEBUG, PSTR("DGR: Checking next_check_time=%u, now=%u"), next_c // If we haven't receive an ack from this member in DGR_MEMBER_TIMEOUT ms, assume // they're offline and remove them from the group. - if ((long)(now - device_group->member_timeout_time) >= 0) { + if ((int32_t)(now - device_group->member_timeout_time) >= 0) { *flink = device_group_member->flink; free(device_group_member); AddLog(LOG_LEVEL_DEBUG, PSTR("DGR: Member %s removed"), IPAddressToString(device_group_member->ip_address)); continue; } - // Otherwise, unicast the last message directly to this member. + // If we have more multicasts to do, multicast the packet to all members again; + // otherwise, unicast the message directly to this member. + if (device_group->multicasts_remaining) device_group_member = nullptr; SendReceiveDeviceGroupMessage(device_group, device_group_member, device_group->message, device_group->message_length, false); - device_group_member->unicast_count++; acked = false; + if (device_group->multicasts_remaining) { + device_group->multicasts_remaining--; + break; + } + device_group_member->unicast_count++; } flink = &device_group_member->flink; } @@ -986,31 +998,34 @@ AddLog(LOG_LEVEL_DEBUG, PSTR("DGR: Checking next_check_time=%u, now=%u"), next_c } // If there are still members we haven't received an ack from, set the next ack check - // time. We start at 200ms and double the interval each pass with a maximum interval of - // 5 seconds. + // time. We start at DGR_ACK_WAIT_TIME ms and add 100ms each pass with a maximum + // interval of 2 seconds. else { - device_group->ack_check_interval *= 2; - if (device_group->ack_check_interval > 5000) device_group->ack_check_interval = 5000; + device_group->ack_check_interval += 100; + if (device_group->ack_check_interval > 2000) device_group->ack_check_interval = 2000; device_group->next_ack_check_time = now + device_group->ack_check_interval; } } } - if (device_group->next_ack_check_time < next_check_time) next_check_time = device_group->next_ack_check_time; + if (device_group->next_ack_check_time && (int32_t)(next_check_time - device_group->next_ack_check_time) > 0) next_check_time = device_group->next_ack_check_time; } - // If it's time to send a multicast announcement for this group, send it. This is to - // announce ourself to any members that have somehow not heard about us. We send it at the - // announcement interval plus a random number of milliseconds so that even if all the devices - // booted at the same time, they don't all multicast their announcements at the same time. + // If we're not still waiting for acks and it's time to send a multicast announcement for this + // group, send it. This is to announce ourself to any members that have somehow not heard + // about us. We send it at the announcement interval plus a random number of milliseconds so + // that even if all the devices booted at the same time, they don't all multicast their + // announcements at the same time. + else { #ifdef DEVICE_GROUPS_DEBUG - AddLog(LOG_LEVEL_DEBUG, PSTR("DGR: next_announcement_time=%u, now=%u"), device_group->next_announcement_time, now); + AddLog(LOG_LEVEL_DEBUG, PSTR("DGR: next_announcement_time=%u, now=%u"), device_group->next_announcement_time, now); #endif // DEVICE_GROUPS_DEBUG - if ((long)(now - device_group->next_announcement_time) >= 0) { - SendReceiveDeviceGroupMessage(device_group, nullptr, device_group->message, BeginDeviceGroupMessage(device_group, DGR_FLAG_ANNOUNCEMENT, true) - device_group->message, false); - device_group->next_announcement_time = now + DGR_ANNOUNCEMENT_INTERVAL + random(10000); + if ((int32_t)(now - device_group->next_announcement_time) >= 0) { + SendReceiveDeviceGroupMessage(device_group, nullptr, device_group->message, BeginDeviceGroupMessage(device_group, DGR_FLAG_ANNOUNCEMENT, true) - device_group->message, false); + device_group->next_announcement_time = now + DGR_ANNOUNCEMENT_INTERVAL + random(10000); + } + if ((int32_t)(next_check_time - device_group->next_announcement_time) > 0) next_check_time = device_group->next_announcement_time; } - if (device_group->next_announcement_time < next_check_time) next_check_time = device_group->next_announcement_time; } } } From 185116aea0ab59b17a3abbde8f3f74627b78c1ca Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sat, 27 Nov 2021 11:01:24 +0100 Subject: [PATCH 131/185] Remove autoconf warning from Berry console --- lib/libesp32/Berry/default/be_autoconf_lib.c | 50 ++++++++++--------- .../Berry/default/embedded/autoconf.be | 2 +- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/lib/libesp32/Berry/default/be_autoconf_lib.c b/lib/libesp32/Berry/default/be_autoconf_lib.c index 9f638d6d7..3d864a988 100644 --- a/lib/libesp32/Berry/default/be_autoconf_lib.c +++ b/lib/libesp32/Berry/default/be_autoconf_lib.c @@ -961,26 +961,28 @@ be_local_closure(init, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[15]) { /* constants */ - /* K0 */ be_nested_string("path", -2071507658, 4), - /* K1 */ be_nested_string("string", 398550328, 6), - /* K2 */ be_nested_string("listdir", 2005220720, 7), - /* K3 */ be_nested_string("/", 705468254, 1), - /* K4 */ be_nested_string("tasmota", 424643812, 7), - /* K5 */ be_nested_string("add_driver", 1654458371, 10), + ( &(const bvalue[17]) { /* constants */ + /* K0 */ be_nested_str_literal("path"), + /* K1 */ be_nested_str_literal("string"), + /* K2 */ be_nested_str_literal("listdir"), + /* K3 */ be_nested_str_literal("/"), + /* K4 */ be_nested_str_literal("tasmota"), + /* K5 */ be_nested_str_literal("add_driver"), /* K6 */ be_const_int(0), - /* K7 */ be_nested_string("find", -1108310694, 4), - /* K8 */ be_nested_string(".autoconf", -1770288208, 9), - /* K9 */ be_nested_string("format", -1180859054, 6), - /* K10 */ be_nested_string("CFG: multiple autoconf files found, aborting ('%s' + '%s')", 197663371, 58), - /* K11 */ be_nested_string("_error", 1132109656, 6), + /* K7 */ be_nested_str_literal("find"), + /* K8 */ be_nested_str_literal(".autoconf"), + /* K9 */ be_nested_str_literal("format"), + /* K10 */ be_nested_str_literal("CFG: multiple autoconf files found, aborting ('%s' + '%s')"), + /* K11 */ be_nested_str_literal("_error"), /* K12 */ be_const_int(1), - /* K13 */ be_nested_string("CFG: no '*.autoconf' file found", 127493957, 31), - /* K14 */ be_nested_string("_archive", -290407892, 8), + /* K13 */ be_nested_str_literal("log"), + /* K14 */ be_nested_str_literal("CFG: no '*.autoconf' file found"), + /* K15 */ be_const_int(2), + /* K16 */ be_nested_str_literal("_archive"), }), (be_nested_const_str("init", 380752755, 4)), ((bstring*) &be_const_str_input), - ( &(const binstruction[49]) { /* code */ + ( &(const binstruction[51]) { /* code */ 0xA4060000, // 0000 IMPORT R1 K0 0xA40A0200, // 0001 IMPORT R2 K1 0x8C0C0302, // 0002 GETMET R3 R1 K2 @@ -1022,14 +1024,16 @@ be_local_closure(init, /* name */ 0x7001FFE3, // 0026 JMP #000B 0x4C180000, // 0027 LDNIL R6 0x1C180806, // 0028 EQ R6 R4 R6 - 0x781A0004, // 0029 JMPF R6 #002F - 0x60180001, // 002A GETGBL R6 G1 - 0x581C000D, // 002B LDCONST R7 K13 - 0x7C180200, // 002C CALL R6 1 - 0x4C180000, // 002D LDNIL R6 - 0x80040C00, // 002E RET 1 R6 - 0x90021C04, // 002F SETMBR R0 K14 R4 - 0x80000000, // 0030 RET 0 + 0x781A0006, // 0029 JMPF R6 #0031 + 0xB81A0800, // 002A GETNGBL R6 K4 + 0x8C180D0D, // 002B GETMET R6 R6 K13 + 0x5820000E, // 002C LDCONST R8 K14 + 0x5824000F, // 002D LDCONST R9 K15 + 0x7C180600, // 002E CALL R6 3 + 0x4C180000, // 002F LDNIL R6 + 0x80040C00, // 0030 RET 1 R6 + 0x90022004, // 0031 SETMBR R0 K16 R4 + 0x80000000, // 0032 RET 0 }) ) ); diff --git a/lib/libesp32/Berry/default/embedded/autoconf.be b/lib/libesp32/Berry/default/embedded/autoconf.be index a30ed2044..8489c7447 100644 --- a/lib/libesp32/Berry/default/embedded/autoconf.be +++ b/lib/libesp32/Berry/default/embedded/autoconf.be @@ -49,7 +49,7 @@ autoconf_module.init = def (m) end if entry == nil - print("CFG: no '*.autoconf' file found") + tasmota.log("CFG: no '*.autoconf' file found", 2) return nil end From f60bd05eed8ce26e57e3995d4cd7329b7c0c50ca Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sat, 27 Nov 2021 11:20:02 +0100 Subject: [PATCH 132/185] Berry fix list.concat --- lib/libesp32/Berry/src/be_listlib.c | 16 +++++---- lib/libesp32/Berry/tests/list.be | 55 +++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 6 deletions(-) diff --git a/lib/libesp32/Berry/src/be_listlib.c b/lib/libesp32/Berry/src/be_listlib.c index aa64ad018..b584aef90 100644 --- a/lib/libesp32/Berry/src/be_listlib.c +++ b/lib/libesp32/Berry/src/be_listlib.c @@ -333,24 +333,23 @@ static int m_merge(bvm *vm) be_return(vm); /* return self */ } -static void connect(bvm *vm, bvalue *begin, bvalue *end, const char * delimiter) +static void connect(bvm *vm, bvalue *begin, bvalue *end, const char * delimiter, bbool first_element) { size_t l0 = be_strlen(vm, -1), len = l0; size_t d = delimiter ? strlen(delimiter) : 0; /* len of delimiter */ - bbool non_empty = l0 > 0; /* is the string non-empty, i.e. needs a prefix delimiter */ char *buf, *p; bvalue *it; for (it = begin; it < end; ++it) { len += str_len(var_tostr(it)) + d; } - if (!non_empty) { + if (first_element) { len -= d; /* remove size for first delimiter non needed */ } buf = be_pushbuffer(vm, len); memcpy(buf, be_tostring(vm, -2), l0); p = buf + l0; for (it = begin; it < end; ++it) { - if ((it != begin || non_empty) && delimiter) { + if ((it != begin || !first_element) && delimiter) { /* add delimiter */ memcpy(p, delimiter, d); p += d; @@ -370,11 +369,15 @@ static void list_concat(bvm *vm, blist *list, const char * delimiter) bvalue *it, *begin = be_list_data(list); bvalue *end = be_list_end(list); be_pushstring(vm, ""); /* push a empty string */ + bbool first_element = btrue; for (it = begin; it < end;) { for (; it < end && var_isstr(it); ++it); - connect(vm, begin, it, delimiter); /* connect string list */ + if (begin < it) { + connect(vm, begin, it, delimiter, first_element); /* connect string list */ + first_element = bfalse; + } if (it < end) { - if (delimiter && be_strlen(vm, -1) > 0) { + if (delimiter && !first_element) { be_pushstring(vm, delimiter); be_strconcat(vm, -2); be_pop(vm, 1); @@ -386,6 +389,7 @@ static void list_concat(bvm *vm, blist *list, const char * delimiter) be_strconcat(vm, -2); be_pop(vm, 1); begin = ++it; + first_element = bfalse; } } } diff --git a/lib/libesp32/Berry/tests/list.be b/lib/libesp32/Berry/tests/list.be index a6ec7ecc7..d0b9099ba 100644 --- a/lib/libesp32/Berry/tests/list.be +++ b/lib/libesp32/Berry/tests/list.be @@ -72,3 +72,58 @@ assert(l2 == [2, 3]) assert(l1+[2] == [0, 1, 2]) assert([-1]+l1 == [-1, 0, 1]) assert(l1 == [0, 1]) + +#- find -# +#- if no argument return nil -# +assert([].find() == nil) +assert([1,2].find() == nil) +assert([1,1,nil,2].find() == nil) + +#- nil if not found -# +assert([1,2].find(3) == nil) +assert([1,2].find(true) == nil) +assert([1,2].find('foo') == nil) + +#- if found -# +assert([1,2,3,4].find(1) == 0) +assert([1,2,3,4].find(2) == 1) +assert([1,2,3,4].find(3) == 2) +assert([1,2,3,4].find(4) == 3) +assert([1,2,"foo",4].find('foo') == 2) + +#- if multiple occurrences -# +assert([1,1,2,2].find(1) == 0) +assert([1,1,2,2].find(2) == 2) + +#- look for nil -# +assert([1,1,nil,2].find(nil) == 2) + +#- sub-structure -# +assert([1,[1,nil,2],3,[3]].find(3) == 2) +assert([1,[1,nil,2],3,[3]].find([3]) == 3) +assert([1,[1,nil,2],3,[3]].find([1,nil,2]) == 1) + +#- keys() -# +assert(str(["a",'b',0].keys()) == "(0..2)") +assert(str([nil].keys()) == "(0..0)") +assert(str([].keys()) == "(0..-1)") + +#- concat with delimiter -# +assert(["foo","bar",0].concat() == "foobar0") +assert([1,2,3].concat() == "123") +assert(["foo","bar",0].concat('') == "foobar0") +assert([1,2,3].concat('') == "123") + +assert(["foo","bar",0].concat('-') == "foo-bar-0") +assert([].concat('<->') == "") +assert(["foo"].concat('<->') == "foo") +assert(["foo","bar",0].concat('<->') == "foo<->bar<->0") + +assert(["","foo","bar",0].concat('<->') == "<->foo<->bar<->0") +assert(["","",1,"bar",0].concat('<->') == "<-><->1<->bar<->0") +assert(["","",1,"bar",0].concat('') == "1bar0") + +assert([1,2,3].concat('-') == "1-2-3") +assert([1,"2",3].concat('-') == "1-2-3") + +assert(["",2,3].concat('-') == "-2-3") From f4d77b9f8b69dc439c772a5f56594db000f7a8d9 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sat, 27 Nov 2021 11:27:09 +0100 Subject: [PATCH 133/185] Berry update pre-compiled `partition.bec` with neest engine --- tasmota/berry/modules/partition.bec | Bin 15584 -> 15637 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/tasmota/berry/modules/partition.bec b/tasmota/berry/modules/partition.bec index 48ce1d2abfe586533deb754b170042627960b504..8a2f56cd3418bfac81145d1e5d44bcac92c4f397 100644 GIT binary patch delta 4037 zcma)9TWlLy89rk>mpXBB96Pa{#K|;?H*u2Yp60S{+GIEB7TPqWZdFhh?{PeKMr+Tw zGn0g@ijqDc1VWJZ2x$@0!ULj00#>Ua#KUS=NGm{E5Emhkc%srG@qnOx03HyC|C}>3 zaqMT8Va$Lj773V1vl9r#apxe zwq4G_796l&b&F(7|zoz;Ido7ZzQpB)_8(lE57Znss^1v~P9hR8S+~`Hzh=^%>{q3MX4Wu!rQh({>QR z3IuUBExnvkEyW-_yS1)U+%Um)uQc3pb@RjYVFS17=);CzO8duv0J)X<0q4u*3Wpm| zo@`pWu?L1QQ(>=STEa9R0yq%Z41e$^FDh^CIYHEROp&ohw5c0PZo9xKNLD(4$y((kBpIZtkZW&4Ixhlsn0(LlAzG0e06= zE&6stClC0;=2ZANs;<44=!U<81_CoOqz@vg?kFtfJY2#kVcR68BoO10?gnm0K~jl) z4mMVqNgoH=!NdBN(|l{Pdv4JWzmPlPS-?)`9V)!hV8m!T3Y-DVRB`D+Wl4!t_+hkeH;dyzl6L=U|Y zF86HvcOtIDCIlq74Hae>I*|R7_O3}dXzAHKDB)V!UUcQ3MX4}b9Jl4M5c&{XnY>VBrWMN3AiLm+ z=w9?@WRm;$rHIw<`ge-ar%e=9zRJ;t`C~r-4H%el{AP%4^0Z*bm z_P@MRn}9wnR=0dF9g6jGb1udHdrp`ts_D34L3mxz@}B5g?L*~lC=4$u@)#Wvm~kJ}~RTI}j<$H5BGC8CjnVg%_oyB4^RKXiS>DyE{zA56vwd~plA zvYuG|>6)czRz@`A3fb}%A)5^d&K^a}!Nxrp5MU&z_=xFpe8q!5Lmv;t=v(m>0QaMK z2drA63)XPYIantLBQHQ)oO9W2%Yq3dh*oZ-(^uCsSC-e8FRor$T~A~BwVrA2%?CZB z-6y=MR@>bBu$r}e%?O$FXTASvK)&$pPSim^kbnE}Qr!f#t)yQ}CPGia0)0Q(38DKFU;mjL zg6E#$B&-MX3amdIz9!)ZBl|qA_eO55o%N#nm)?=8qd! zucz6h+lW#{Qp)DY663=7C{wgHDs#Ew?f$4}=|3Jl&%Pf0d-Sfaw&eFg@NxDkS}1Vd z7BMr#C;$hsM8U*o6hx4Dk~ziIPL}QHl08(rV&(os4$xQGW!x-8L>j8`kLman&O>cl0!O*B0$|jo!$Ilz4bqD9jP}~rlKq{t()AMam^D0oP zp^>7~dZ8VGrhiQ{yvQ@7esHJ^w=pY^>CKrJ;p2mufe>y*H?-F^eOHq=^%4+!4#PCx zb+Lw{TN(e8k^(wp(c7Pkp+{!VJum%!b#{(J>*upuP>df_dbKd2ugMO&`tmg5T17AFKoOld!tw t`IK_<3e0Nrofp5=3SbbIXK_!anUokVzL2`m#abl4Sla^?zgBWt=>PYMK>`2( delta 4158 zcma)9OKcn06@C0XeJJWfQ9p{ZJeEXDlqiXkDBF@LSyCd!X(B~#yiyCm^paB9nO|of$wgFmn(-Z}|h=U?U(JW&W{oMQB z%y2|HM!6V}oHzG-&bfDPz3|t=o_BxuA1{GVH(uc5Cq-E;1<8%b$D_27lx5viO;syV zO7gq1u|w;KVd`qB05=bmtfA=picVS5*W;mV$xr?K#h(z0VZu{z z*HB-;pSyBa*`;uX2U#$vj}#QsgNb?YVUG_DV36~)fyjoHfs;xd$!mI1Hfe;YrG0r< z%}GVMpl(a0y<%3;rC4(M3T5B%4MSw?=f1bT0rXOmD2UBMW*EAT4ka(2w<_lsi= zki4!HtvKui*f0D8=;6=)rRHO1*a)4#qI{L^c(%Z)YGj~*P95yl_#qlO$1}Dn05K4# zv0-ZEjA|;n%v)KTH+ztZvSfWHdcRnI#qrLcXSeGyth;}x|E=e!(toh*ZVx11F1r%0 zCwY0>)bv9L1%rjNieZZ2`~<)t!(q6=zxhac=g=-P0Nf@8B>DF#ky9Pfz_DUlC`b~v92{etL3*kN^me}} zfsPmoW#0`-Sou4_bhuJqCvx`R;8W+Ji%?E=U%}4vnu$O}JX7#kQGOn7VaI^PYDqQ4 z73^Mb{`!P-peovGvm!Cp)^Z9XO0~S6sPXK|J!xAL&MEt>We}h1YJLA{t5Q~gRRVOwNQFdk${VBhvB z_>Yz?_cc9WQfL$-T@OhhT&2)lGYFcaMRn}0&?MgeB=piHfzu46h|t;9OaqK^UBXIK zATR1-i&G8jDrjeKwsR4x?M^g~ zAh5ZPI2u+uOfT)e+1zro})9?!MvU2D3ZYO{y0zKaY=IXizGo!gHIt6|#o3)|%$ok{6 zfLm*HNMv5ZXyhZs+$?23>E(j=VegGz*9ks+D`S`)MkkL8W>GH51x2r8_o8zc$b;y|NGsQ# zaAzvAaBQt`kq$Ykl}x2%X2g7VX|c2}Ov8?Gq9cS`g?&;f<>(T7?QADo@2_VspNM(s z*H|7gCKn}U)tcC>>GFi7k&24(l=qF#F5dTe-+cDl~#igOa`Wjo65nI^13 zA+mCLYwMYf%=+@i@)N7;s~cOCz1cs5>He)h(RVD}sxVpdI-BoGjvNFJ;Pp%Mc|Kna}s+y zmcX)p68qzkgF;8^!mf^0`c;vw>cIw$sjw1MM>dMU8yt&D5w{eZ;C2%>qFd zr`g)@V-VQgSBI~8CTM_{QWRR0(T(_O2=vA`y8*sfeWWdp6T2tu<#=ZwD%Tf<#@>v_ z9@_p-f$7Q!Ap#(&$J79VTh4J9}wx01EuZIR&nN8pTG9jU8d3 zZ;xGxAH%Pg0OA|TB-S@mEa)&jE^cjYW}a9D&`%^H_|TUUBZI(PPBZ%)f(fLjfuwik zVm2o)igV!UmkGWf+)rG<0uGOV+g~dXN8qy3QMW+UlO5T}$a(>E3Y!Nzr(O^>=Z)to zSi9YJk|(XL-Z3i;#&Uo}_dIf%(k;4DO%cj6(_N6l{&f5ZnvTLNnqD(XpiHo~s=Bg` z8|mZ)-7puxnLrPxn*--ZblV1^8@GMrY1uF()<4q?k(`-H4cp-9BhPL=xwiJKglqJ zTeY6EtFsHI|4;3GclIno>GRng;Nl~gR|^aFy|Zhf8r5X?&&EdVs-CEDiWhcXLT0&$ zHGK}bbot!WL+FKq_R(mR&CI2|^vf(UHphN6*9*r%+in{^h Date: Sat, 27 Nov 2021 18:47:24 +0100 Subject: [PATCH 134/185] Berry add `bool()` function --- lib/libesp32/Berry/src/be_baselib.c | 15 ++++++++++++++- lib/libesp32/Berry/src/be_libs.c | 4 ++-- lib/libesp32/Berry/tests/bool.be | 21 +++++++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/lib/libesp32/Berry/src/be_baselib.c b/lib/libesp32/Berry/src/be_baselib.c index f80b321b1..6e92b47be 100644 --- a/lib/libesp32/Berry/src/be_baselib.c +++ b/lib/libesp32/Berry/src/be_baselib.c @@ -340,6 +340,17 @@ static int l_str(bvm *vm) be_return(vm); } +static int l_bool(bvm *vm) +{ + if (be_top(vm)) { + be_pushbool(vm, be_tobool(vm, 1)); + } else { + be_pushbool(vm, bfalse); + } + be_return(vm); +} + + static int l_size(bvm *vm) { if (be_top(vm) && be_isstring(vm, 1)) { @@ -462,9 +473,10 @@ void be_load_baselib(bvm *vm) } /* call must be added later to respect order of builtins */ -void be_load_baselib_call(bvm *vm) +void be_load_baselib_next(bvm *vm) { be_regfunc(vm, "call", l_call); + be_regfunc(vm, "bool", l_bool); } #else extern const bclass be_class_list; @@ -497,6 +509,7 @@ vartab m_builtin (scope: local) { range, class(be_class_range) bytes, class(be_class_bytes) call, func(l_call) + bool, func(l_bool) } @const_object_info_end */ #include "../generate/be_fixed_m_builtin.h" diff --git a/lib/libesp32/Berry/src/be_libs.c b/lib/libesp32/Berry/src/be_libs.c index 0c55717f3..a9a2f0e39 100644 --- a/lib/libesp32/Berry/src/be_libs.c +++ b/lib/libesp32/Berry/src/be_libs.c @@ -8,7 +8,7 @@ #include "be_libs.h" extern void be_load_baselib(bvm *vm); -extern void be_load_baselib_call(bvm *vm); +extern void be_load_baselib_next(bvm *vm); extern void be_load_listlib(bvm *vm); extern void be_load_maplib(bvm *vm); extern void be_load_rangelib(bvm *vm); @@ -24,6 +24,6 @@ void be_loadlibs(bvm *vm) be_load_rangelib(vm); be_load_filelib(vm); be_load_byteslib(vm); - be_load_baselib_call(vm); + be_load_baselib_next(vm); #endif } diff --git a/lib/libesp32/Berry/tests/bool.be b/lib/libesp32/Berry/tests/bool.be index 670f9bfd8..807d36148 100644 --- a/lib/libesp32/Berry/tests/bool.be +++ b/lib/libesp32/Berry/tests/bool.be @@ -16,3 +16,24 @@ def test(a, b) end end test(true, true) + +# bug in unary +def f(i) + var j = !i # bug if i is erroneously modified + return i +end +assert(f(1) == 1) + +#- addind bool() function -# +assert(bool() == false) +assert(bool(0) == false) +assert(bool(0.0) == false) +assert(bool(false) == false) +assert(bool(nil) == false) + +assert(bool(-1) == true) +assert(bool(3.5) == true) +assert(bool('') == true) +assert(bool('a') == true) +assert(bool(list) == true) +assert(bool(list()) == true) From 85472e1be4b2b235518dac64a6af5f741eb45594 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sat, 27 Nov 2021 19:33:11 +0100 Subject: [PATCH 135/185] Berry Leds support for serpentine matrix --- lib/libesp32/Berry/default/be_leds_lib.c | 191 +++++++++--------- .../Berry/default/be_leds_matrix_lib.c | 145 ++++++++++--- lib/libesp32/Berry/default/be_leds_ntv_lib.c | 37 +--- lib/libesp32/Berry/default/embedded/leds.be | 57 +++++- lib/libesp32/Berry/src/be_constobj.h | 3 + lib/libesp32/Berry/src/be_solidifylib.c | 2 +- tasmota/berry/leds/rainbow.be | 4 +- 7 files changed, 277 insertions(+), 162 deletions(-) diff --git a/lib/libesp32/Berry/default/be_leds_lib.c b/lib/libesp32/Berry/default/be_leds_lib.c index 7ddaa4b16..a4442df37 100644 --- a/lib/libesp32/Berry/default/be_leds_lib.c +++ b/lib/libesp32/Berry/default/be_leds_lib.c @@ -9,7 +9,7 @@ /******************************************************************** ** Solidified function: get_pixel_color ********************************************************************/ -be_local_closure(get_pixel_color, /* name */ +be_local_closure(Leds_get_pixel_color, /* name */ be_nested_proto( 6, /* nstack */ 2, /* argc */ @@ -20,7 +20,7 @@ be_local_closure(get_pixel_color, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_string("call_native", 1389147405, 11), + /* K0 */ be_nested_str_literal("call_native"), }), (be_nested_const_str("get_pixel_color", 337490048, 15)), ((bstring*) &be_const_str_input), @@ -39,7 +39,7 @@ be_local_closure(get_pixel_color, /* name */ /******************************************************************** ** Solidified function: pixels_buffer ********************************************************************/ -be_local_closure(pixels_buffer, /* name */ +be_local_closure(Leds_pixels_buffer, /* name */ be_nested_proto( 4, /* nstack */ 1, /* argc */ @@ -50,7 +50,7 @@ be_local_closure(pixels_buffer, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_string("call_native", 1389147405, 11), + /* K0 */ be_nested_str_literal("call_native"), }), (be_nested_const_str("pixels_buffer", 1229555807, 13)), ((bstring*) &be_const_str_input), @@ -68,7 +68,7 @@ be_local_closure(pixels_buffer, /* name */ /******************************************************************** ** Solidified function: clear ********************************************************************/ -be_local_closure(clear, /* name */ +be_local_closure(Leds_clear, /* name */ be_nested_proto( 4, /* nstack */ 1, /* argc */ @@ -79,9 +79,9 @@ be_local_closure(clear, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_string("clear_to", -766965166, 8), + /* K0 */ be_nested_str_literal("clear_to"), /* K1 */ be_const_int(0), - /* K2 */ be_nested_string("show", -1454906820, 4), + /* K2 */ be_nested_str_literal("show"), }), (be_nested_const_str("clear", 1550717474, 5)), ((bstring*) &be_const_str_input), @@ -101,10 +101,10 @@ be_local_closure(clear, /* name */ /******************************************************************** ** Solidified function: init ********************************************************************/ -be_local_closure(init, /* name */ +be_local_closure(Leds_init, /* name */ be_nested_proto( - 9, /* nstack */ - 4, /* argc */ + 11, /* nstack */ + 5, /* argc */ 0, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ @@ -112,52 +112,53 @@ be_local_closure(init, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[11]) { /* constants */ - /* K0 */ be_nested_string("gamma", -802614262, 5), - /* K1 */ be_nested_string("pin", 1866532500, 3), - /* K2 */ be_nested_string("WS2812", -755226078, 6), + /* K0 */ be_nested_str_literal("gamma"), + /* K1 */ be_nested_str_literal("pin"), + /* K2 */ be_nested_str_literal("WS2812"), /* K3 */ be_const_int(0), - /* K4 */ be_nested_string("valuer_error", -1727020191, 12), - /* K5 */ be_nested_string("no GPIO specified for neopixelbus", 42078528, 33), - /* K6 */ be_nested_string("ctor", 375399343, 4), - /* K7 */ be_nested_string("_p", 1594591802, 2), - /* K8 */ be_nested_string("internal_error", -1775809127, 14), - /* K9 */ be_nested_string("couldn't not initialize noepixelbus", -1758476484, 35), - /* K10 */ be_nested_string("begin", 1748273790, 5), + /* K4 */ be_nested_str_literal("valuer_error"), + /* K5 */ be_nested_str_literal("no GPIO specified for neopixelbus"), + /* K6 */ be_nested_str_literal("ctor"), + /* K7 */ be_nested_str_literal("_p"), + /* K8 */ be_nested_str_literal("internal_error"), + /* K9 */ be_nested_str_literal("couldn't not initialize noepixelbus"), + /* K10 */ be_nested_str_literal("begin"), }), (be_nested_const_str("init", 380752755, 4)), ((bstring*) &be_const_str_input), - ( &(const binstruction[31]) { /* code */ - 0x50100200, // 0000 LDBOOL R4 1 0 - 0x90020004, // 0001 SETMBR R0 K0 R4 - 0x4C100000, // 0002 LDNIL R4 - 0x1C100404, // 0003 EQ R4 R2 R4 - 0x78120008, // 0004 JMPF R4 #000E - 0x8C100501, // 0005 GETMET R4 R2 K1 - 0x88180502, // 0006 GETMBR R6 R2 K2 - 0x7C100400, // 0007 CALL R4 2 - 0x28100903, // 0008 GE R4 R4 K3 - 0x78120003, // 0009 JMPF R4 #000E - 0x8C100501, // 000A GETMET R4 R2 K1 - 0x88180502, // 000B GETMBR R6 R2 K2 - 0x7C100400, // 000C CALL R4 2 - 0x5C080800, // 000D MOVE R2 R4 - 0x4C100000, // 000E LDNIL R4 - 0x1C100404, // 000F EQ R4 R2 R4 - 0x78120000, // 0010 JMPF R4 #0012 + ( &(const binstruction[32]) { /* code */ + 0x50140200, // 0000 LDBOOL R5 1 0 + 0x90020005, // 0001 SETMBR R0 K0 R5 + 0x4C140000, // 0002 LDNIL R5 + 0x1C140405, // 0003 EQ R5 R2 R5 + 0x78160008, // 0004 JMPF R5 #000E + 0x8C140501, // 0005 GETMET R5 R2 K1 + 0x881C0502, // 0006 GETMBR R7 R2 K2 + 0x7C140400, // 0007 CALL R5 2 + 0x28140B03, // 0008 GE R5 R5 K3 + 0x78160003, // 0009 JMPF R5 #000E + 0x8C140501, // 000A GETMET R5 R2 K1 + 0x881C0502, // 000B GETMBR R7 R2 K2 + 0x7C140400, // 000C CALL R5 2 + 0x5C080A00, // 000D MOVE R2 R5 + 0x4C140000, // 000E LDNIL R5 + 0x1C140405, // 000F EQ R5 R2 R5 + 0x78160000, // 0010 JMPF R5 #0012 0xB0060905, // 0011 RAISE 1 K4 K5 - 0x8C100106, // 0012 GETMET R4 R0 K6 - 0x5C180200, // 0013 MOVE R6 R1 - 0x5C1C0400, // 0014 MOVE R7 R2 - 0x5C200600, // 0015 MOVE R8 R3 - 0x7C100800, // 0016 CALL R4 4 - 0x88100107, // 0017 GETMBR R4 R0 K7 - 0x4C140000, // 0018 LDNIL R5 - 0x1C100805, // 0019 EQ R4 R4 R5 - 0x78120000, // 001A JMPF R4 #001C - 0xB0061109, // 001B RAISE 1 K8 K9 - 0x8C10010A, // 001C GETMET R4 R0 K10 - 0x7C100200, // 001D CALL R4 1 - 0x80000000, // 001E RET 0 + 0x8C140106, // 0012 GETMET R5 R0 K6 + 0x5C1C0200, // 0013 MOVE R7 R1 + 0x5C200400, // 0014 MOVE R8 R2 + 0x5C240600, // 0015 MOVE R9 R3 + 0x5C280800, // 0016 MOVE R10 R4 + 0x7C140A00, // 0017 CALL R5 5 + 0x88140107, // 0018 GETMBR R5 R0 K7 + 0x4C180000, // 0019 LDNIL R6 + 0x1C140A06, // 001A EQ R5 R5 R6 + 0x78160000, // 001B JMPF R5 #001D + 0xB0061109, // 001C RAISE 1 K8 K9 + 0x8C14010A, // 001D GETMET R5 R0 K10 + 0x7C140200, // 001E CALL R5 1 + 0x80000000, // 001F RET 0 }) ) ); @@ -167,7 +168,7 @@ be_local_closure(init, /* name */ /******************************************************************** ** Solidified function: set_pixel_color ********************************************************************/ -be_local_closure(set_pixel_color, /* name */ +be_local_closure(Leds_set_pixel_color, /* name */ be_nested_proto( 12, /* nstack */ 4, /* argc */ @@ -178,8 +179,8 @@ be_local_closure(set_pixel_color, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_string("call_native", 1389147405, 11), - /* K1 */ be_nested_string("to_gamma", 1597139862, 8), + /* K0 */ be_nested_str_literal("call_native"), + /* K1 */ be_nested_str_literal("to_gamma"), }), (be_nested_const_str("set_pixel_color", 1275248356, 15)), ((bstring*) &be_const_str_input), @@ -202,7 +203,7 @@ be_local_closure(set_pixel_color, /* name */ /******************************************************************** ** Solidified function: begin ********************************************************************/ -be_local_closure(begin, /* name */ +be_local_closure(Leds_begin, /* name */ be_nested_proto( 4, /* nstack */ 1, /* argc */ @@ -213,7 +214,7 @@ be_local_closure(begin, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_string("call_native", 1389147405, 11), + /* K0 */ be_nested_str_literal("call_native"), /* K1 */ be_const_int(1), }), (be_nested_const_str("begin", 1748273790, 5)), @@ -232,7 +233,7 @@ be_local_closure(begin, /* name */ /******************************************************************** ** Solidified function: to_gamma ********************************************************************/ -be_local_closure(to_gamma, /* name */ +be_local_closure(Leds_to_gamma, /* name */ be_nested_proto( 12, /* nstack */ 3, /* argc */ @@ -243,13 +244,13 @@ be_local_closure(to_gamma, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 7]) { /* constants */ - /* K0 */ be_nested_string("tasmota", 424643812, 7), - /* K1 */ be_nested_string("scale_uint", -1204156202, 10), + /* K0 */ be_nested_str_literal("tasmota"), + /* K1 */ be_nested_str_literal("scale_uint"), /* K2 */ be_const_int(0), /* K3 */ be_const_int(16711680), - /* K4 */ be_nested_string("gamma", -802614262, 5), - /* K5 */ be_nested_string("light", -493019601, 5), - /* K6 */ be_nested_string("gamma8", -492123466, 6), + /* K4 */ be_nested_str_literal("gamma"), + /* K5 */ be_nested_str_literal("light"), + /* K6 */ be_nested_str_literal("gamma8"), }), (be_nested_const_str("to_gamma", 1597139862, 8)), ((bstring*) &be_const_str_input), @@ -330,7 +331,7 @@ be_local_closure(to_gamma, /* name */ /******************************************************************** ** Solidified function: pixel_count ********************************************************************/ -be_local_closure(pixel_count, /* name */ +be_local_closure(Leds_pixel_count, /* name */ be_nested_proto( 4, /* nstack */ 1, /* argc */ @@ -341,7 +342,7 @@ be_local_closure(pixel_count, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_string("call_native", 1389147405, 11), + /* K0 */ be_nested_str_literal("call_native"), }), (be_nested_const_str("pixel_count", -1855836553, 11)), ((bstring*) &be_const_str_input), @@ -359,7 +360,7 @@ be_local_closure(pixel_count, /* name */ /******************************************************************** ** Solidified function: can_show ********************************************************************/ -be_local_closure(can_show, /* name */ +be_local_closure(Leds_can_show, /* name */ be_nested_proto( 4, /* nstack */ 1, /* argc */ @@ -370,7 +371,7 @@ be_local_closure(can_show, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_string("call_native", 1389147405, 11), + /* K0 */ be_nested_str_literal("call_native"), /* K1 */ be_const_int(3), }), (be_nested_const_str("can_show", 960091187, 8)), @@ -389,7 +390,7 @@ be_local_closure(can_show, /* name */ /******************************************************************** ** Solidified function: pixel_size ********************************************************************/ -be_local_closure(pixel_size, /* name */ +be_local_closure(Leds_pixel_size, /* name */ be_nested_proto( 4, /* nstack */ 1, /* argc */ @@ -400,7 +401,7 @@ be_local_closure(pixel_size, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_string("call_native", 1389147405, 11), + /* K0 */ be_nested_str_literal("call_native"), }), (be_nested_const_str("pixel_size", -2085831511, 10)), ((bstring*) &be_const_str_input), @@ -418,7 +419,7 @@ be_local_closure(pixel_size, /* name */ /******************************************************************** ** Solidified function: dirty ********************************************************************/ -be_local_closure(dirty, /* name */ +be_local_closure(Leds_dirty, /* name */ be_nested_proto( 4, /* nstack */ 1, /* argc */ @@ -429,7 +430,7 @@ be_local_closure(dirty, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_string("call_native", 1389147405, 11), + /* K0 */ be_nested_str_literal("call_native"), }), (be_nested_const_str("dirty", -1627386213, 5)), ((bstring*) &be_const_str_input), @@ -447,7 +448,7 @@ be_local_closure(dirty, /* name */ /******************************************************************** ** Solidified function: show ********************************************************************/ -be_local_closure(show, /* name */ +be_local_closure(Leds_show, /* name */ be_nested_proto( 4, /* nstack */ 1, /* argc */ @@ -458,7 +459,7 @@ be_local_closure(show, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_string("call_native", 1389147405, 11), + /* K0 */ be_nested_str_literal("call_native"), /* K1 */ be_const_int(2), }), (be_nested_const_str("show", -1454906820, 4)), @@ -477,7 +478,7 @@ be_local_closure(show, /* name */ /******************************************************************** ** Solidified function: clear_to ********************************************************************/ -be_local_closure(clear_to, /* name */ +be_local_closure(Leds_clear_to, /* name */ be_nested_proto( 10, /* nstack */ 3, /* argc */ @@ -488,8 +489,8 @@ be_local_closure(clear_to, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_string("call_native", 1389147405, 11), - /* K1 */ be_nested_string("to_gamma", 1597139862, 8), + /* K0 */ be_nested_str_literal("call_native"), + /* K1 */ be_nested_str_literal("to_gamma"), }), (be_nested_const_str("clear_to", -766965166, 8)), ((bstring*) &be_const_str_input), @@ -511,7 +512,7 @@ be_local_closure(clear_to, /* name */ /******************************************************************** ** Solidified function: is_dirty ********************************************************************/ -be_local_closure(is_dirty, /* name */ +be_local_closure(Leds_is_dirty, /* name */ be_nested_proto( 4, /* nstack */ 1, /* argc */ @@ -522,7 +523,7 @@ be_local_closure(is_dirty, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_string("call_native", 1389147405, 11), + /* K0 */ be_nested_str_literal("call_native"), }), (be_nested_const_str("is_dirty", 418034110, 8)), ((bstring*) &be_const_str_input), @@ -540,7 +541,7 @@ be_local_closure(is_dirty, /* name */ /******************************************************************** ** Solidified function: ctor ********************************************************************/ -be_local_closure(ctor, /* name */ +be_local_closure(Leds_ctor, /* name */ be_nested_proto( 10, /* nstack */ 4, /* argc */ @@ -551,7 +552,7 @@ be_local_closure(ctor, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_string("call_native", 1389147405, 11), + /* K0 */ be_nested_str_literal("call_native"), /* K1 */ be_const_int(0), }), (be_nested_const_str("ctor", 375399343, 4)), @@ -588,24 +589,24 @@ be_local_class(Leds, &be_class_Leds_ntv, be_nested_map(16, ( (struct bmapnode*) &(const bmapnode[]) { - { be_nested_key("get_pixel_color", 337490048, 15, -1), be_const_closure(get_pixel_color_closure) }, - { be_nested_key("pixels_buffer", 1229555807, 13, -1), be_const_closure(pixels_buffer_closure) }, - { be_nested_key("clear", 1550717474, 5, 13), be_const_closure(clear_closure) }, - { be_nested_key("init", 380752755, 4, 8), be_const_closure(init_closure) }, - { be_nested_key("set_pixel_color", 1275248356, 15, -1), be_const_closure(set_pixel_color_closure) }, - { be_nested_key("begin", 1748273790, 5, -1), be_const_closure(begin_closure) }, - { be_nested_key("to_gamma", 1597139862, 8, -1), be_const_closure(to_gamma_closure) }, - { be_nested_key("pixel_count", -1855836553, 11, -1), be_const_closure(pixel_count_closure) }, - { be_nested_key("can_show", 960091187, 8, -1), be_const_closure(can_show_closure) }, - { be_nested_key("pixel_size", -2085831511, 10, -1), be_const_closure(pixel_size_closure) }, + { be_nested_key("get_pixel_color", 337490048, 15, -1), be_const_closure(Leds_get_pixel_color_closure) }, + { be_nested_key("ctor", 375399343, 4, -1), be_const_closure(Leds_ctor_closure) }, + { be_nested_key("clear", 1550717474, 5, 8), be_const_closure(Leds_clear_closure) }, + { be_nested_key("init", 380752755, 4, 13), be_const_closure(Leds_init_closure) }, + { be_nested_key("set_pixel_color", 1275248356, 15, -1), be_const_closure(Leds_set_pixel_color_closure) }, + { be_nested_key("is_dirty", 418034110, 8, -1), be_const_closure(Leds_is_dirty_closure) }, + { be_nested_key("to_gamma", 1597139862, 8, -1), be_const_closure(Leds_to_gamma_closure) }, + { be_nested_key("pixel_count", -1855836553, 11, -1), be_const_closure(Leds_pixel_count_closure) }, + { be_nested_key("clear_to", -766965166, 8, -1), be_const_closure(Leds_clear_to_closure) }, + { be_nested_key("pixel_size", -2085831511, 10, -1), be_const_closure(Leds_pixel_size_closure) }, { be_nested_key("gamma", -802614262, 5, -1), be_const_var(0) }, - { be_nested_key("dirty", -1627386213, 5, -1), be_const_closure(dirty_closure) }, - { be_nested_key("show", -1454906820, 4, -1), be_const_closure(show_closure) }, - { be_nested_key("clear_to", -766965166, 8, -1), be_const_closure(clear_to_closure) }, - { be_nested_key("is_dirty", 418034110, 8, 5), be_const_closure(is_dirty_closure) }, - { be_nested_key("ctor", 375399343, 4, 1), be_const_closure(ctor_closure) }, + { be_nested_key("dirty", -1627386213, 5, -1), be_const_closure(Leds_dirty_closure) }, + { be_nested_key("show", -1454906820, 4, -1), be_const_closure(Leds_show_closure) }, + { be_nested_key("can_show", 960091187, 8, -1), be_const_closure(Leds_can_show_closure) }, + { be_nested_key("begin", 1748273790, 5, 5), be_const_closure(Leds_begin_closure) }, + { be_nested_key("pixels_buffer", 1229555807, 13, 1), be_const_closure(Leds_pixels_buffer_closure) }, })), - (be_nested_const_str("Leds", -1585722021, 4)) + be_str_literal("Leds") ); /*******************************************************************/ diff --git a/lib/libesp32/Berry/default/be_leds_matrix_lib.c b/lib/libesp32/Berry/default/be_leds_matrix_lib.c index b6d83bb18..1aafb3db4 100644 --- a/lib/libesp32/Berry/default/be_leds_matrix_lib.c +++ b/lib/libesp32/Berry/default/be_leds_matrix_lib.c @@ -6,10 +6,64 @@ #ifdef USE_WS2812 +/******************************************************************** +** Solidified function: get_alternate +********************************************************************/ +be_local_closure(Leds_matrix_get_alternate, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_literal("alternate"), + }), + (be_nested_const_str("get_alternate", 1450148894, 13)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_alternate +********************************************************************/ +be_local_closure(Leds_matrix_set_alternate, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_literal("alternate"), + }), + (be_nested_const_str("set_alternate", 1709680562, 13)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: set_matrix_pixel_color ********************************************************************/ -be_local_closure(set_matrix_pixel_color, /* name */ +be_local_closure(Leds_matrix_set_matrix_pixel_color, /* name */ be_nested_proto( 10, /* nstack */ 5, /* argc */ @@ -19,21 +73,40 @@ be_local_closure(set_matrix_pixel_color, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_string("set_pixel_color", 1275248356, 15), - /* K1 */ be_nested_string("w", -234078410, 1), + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_literal("alternate"), + /* K1 */ be_const_int(2), + /* K2 */ be_nested_str_literal("set_pixel_color"), + /* K3 */ be_nested_str_literal("w"), + /* K4 */ be_nested_str_literal("h"), + /* K5 */ be_const_int(1), }), (be_nested_const_str("set_matrix_pixel_color", 1197149462, 22)), ((bstring*) &be_const_str_input), - ( &(const binstruction[ 8]) { /* code */ - 0x8C140100, // 0000 GETMET R5 R0 K0 - 0x881C0101, // 0001 GETMBR R7 R0 K1 - 0x081C0207, // 0002 MUL R7 R1 R7 - 0x001C0E02, // 0003 ADD R7 R7 R2 - 0x5C200600, // 0004 MOVE R8 R3 - 0x5C240800, // 0005 MOVE R9 R4 - 0x7C140800, // 0006 CALL R5 4 - 0x80000000, // 0007 RET 0 + ( &(const binstruction[23]) { /* code */ + 0x88140100, // 0000 GETMBR R5 R0 K0 + 0x7816000C, // 0001 JMPF R5 #000F + 0x10140301, // 0002 MOD R5 R1 K1 + 0x7816000A, // 0003 JMPF R5 #000F + 0x8C140102, // 0004 GETMET R5 R0 K2 + 0x881C0103, // 0005 GETMBR R7 R0 K3 + 0x081C0207, // 0006 MUL R7 R1 R7 + 0x88200104, // 0007 GETMBR R8 R0 K4 + 0x001C0E08, // 0008 ADD R7 R7 R8 + 0x041C0E02, // 0009 SUB R7 R7 R2 + 0x041C0F05, // 000A SUB R7 R7 K5 + 0x5C200600, // 000B MOVE R8 R3 + 0x5C240800, // 000C MOVE R9 R4 + 0x7C140800, // 000D CALL R5 4 + 0x70020006, // 000E JMP #0016 + 0x8C140102, // 000F GETMET R5 R0 K2 + 0x881C0103, // 0010 GETMBR R7 R0 K3 + 0x081C0207, // 0011 MUL R7 R1 R7 + 0x001C0E02, // 0012 ADD R7 R7 R2 + 0x5C200600, // 0013 MOVE R8 R3 + 0x5C240800, // 0014 MOVE R9 R4 + 0x7C140800, // 0015 CALL R5 4 + 0x80000000, // 0016 RET 0 }) ) ); @@ -43,7 +116,7 @@ be_local_closure(set_matrix_pixel_color, /* name */ /******************************************************************** ** Solidified function: init ********************************************************************/ -be_local_closure(init, /* name */ +be_local_closure(Leds_matrix_init, /* name */ be_nested_proto( 10, /* nstack */ 5, /* argc */ @@ -53,25 +126,28 @@ be_local_closure(init, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_string("w", -234078410, 1), - /* K1 */ be_nested_string("h", -317966505, 1), - /* K2 */ be_nested_string("init", 380752755, 4), + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_literal("w"), + /* K1 */ be_nested_str_literal("h"), + /* K2 */ be_nested_str_literal("alternate"), + /* K3 */ be_nested_str_literal("init"), }), (be_nested_const_str("init", 380752755, 4)), ((bstring*) &be_const_str_input), - ( &(const binstruction[11]) { /* code */ + ( &(const binstruction[13]) { /* code */ 0x90020001, // 0000 SETMBR R0 K0 R1 0x90020202, // 0001 SETMBR R0 K1 R2 - 0x60140003, // 0002 GETGBL R5 G3 - 0x5C180000, // 0003 MOVE R6 R0 - 0x7C140200, // 0004 CALL R5 1 - 0x8C140B02, // 0005 GETMET R5 R5 K2 - 0x081C0202, // 0006 MUL R7 R1 R2 - 0x5C200600, // 0007 MOVE R8 R3 - 0x5C240800, // 0008 MOVE R9 R4 - 0x7C140800, // 0009 CALL R5 4 - 0x80000000, // 000A RET 0 + 0x50140000, // 0002 LDBOOL R5 0 0 + 0x90020405, // 0003 SETMBR R0 K2 R5 + 0x60140003, // 0004 GETGBL R5 G3 + 0x5C180000, // 0005 MOVE R6 R0 + 0x7C140200, // 0006 CALL R5 1 + 0x8C140B03, // 0007 GETMET R5 R5 K3 + 0x081C0202, // 0008 MUL R7 R1 R2 + 0x5C200600, // 0009 MOVE R8 R3 + 0x5C240800, // 000A MOVE R9 R4 + 0x7C140800, // 000B CALL R5 4 + 0x80000000, // 000C RET 0 }) ) ); @@ -83,16 +159,19 @@ be_local_closure(init, /* name */ ********************************************************************/ extern const bclass be_class_Leds; be_local_class(Leds_matrix, - 2, + 3, &be_class_Leds, - be_nested_map(4, + be_nested_map(7, ( (struct bmapnode*) &(const bmapnode[]) { + { be_nested_key("init", 380752755, 4, 3), be_const_closure(Leds_matrix_init_closure) }, { be_nested_key("h", -317966505, 1, -1), be_const_var(0) }, + { be_nested_key("set_alternate", 1709680562, 13, 6), be_const_closure(Leds_matrix_set_alternate_closure) }, + { be_nested_key("set_matrix_pixel_color", 1197149462, 22, 4), be_const_closure(Leds_matrix_set_matrix_pixel_color_closure) }, { be_nested_key("w", -234078410, 1, -1), be_const_var(1) }, - { be_nested_key("set_matrix_pixel_color", 1197149462, 22, 1), be_const_closure(set_matrix_pixel_color_closure) }, - { be_nested_key("init", 380752755, 4, 0), be_const_closure(init_closure) }, + { be_nested_key("get_alternate", 1450148894, 13, 0), be_const_closure(Leds_matrix_get_alternate_closure) }, + { be_nested_key("alternate", 1140253277, 9, -1), be_const_var(2) }, })), - (be_nested_const_str("Leds_matrix", -1450073227, 11)) + be_str_literal("Leds_matrix") ); /*******************************************************************/ diff --git a/lib/libesp32/Berry/default/be_leds_ntv_lib.c b/lib/libesp32/Berry/default/be_leds_ntv_lib.c index 8d09f952b..5affc1c71 100644 --- a/lib/libesp32/Berry/default/be_leds_ntv_lib.c +++ b/lib/libesp32/Berry/default/be_leds_ntv_lib.c @@ -23,29 +23,6 @@ end extern int be_neopixelbus_call_native(bvm *vm); -/******************************************************************** -** Solidified function: call_native -********************************************************************/ -be_local_closure(call_native, /* name */ - be_nested_proto( - 1, /* nstack */ - 1, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ - (be_nested_const_str("call_native", 1389147405, 11)), - ((bstring*) &be_const_str_input), - ( &(const binstruction[ 1]) { /* code */ - 0x80000000, // 0000 RET 0 - }) - ) -); -/*******************************************************************/ - /******************************************************************** ** Solidified class: Leds_ntv @@ -55,15 +32,15 @@ be_local_class(Leds_ntv, NULL, be_nested_map(7, ( (struct bmapnode*) &(const bmapnode[]) { - { be_nested_key("WS2812_GRB", 1736405692, 10, 3), be_const_int(1) }, - { be_nested_key("WS2812_GRBW", -660477967, 11, -1), be_const_int(2) }, - { be_nested_key("call_native", 1389147405, 11, 1), be_const_func(be_neopixelbus_call_native) }, - { be_nested_key("_t", 1527481326, 2, -1), be_const_var(1) }, + { be_nested_key("WS2812_GRB", 1736405692, 10, 5), be_const_int(1) }, + { be_nested_key("_p", 1594591802, 2, -1), be_const_var(0) }, + { be_nested_key("WS2812_GRBW", -660477967, 11, 3), be_const_int(2) }, + { be_nested_key("call_native", 1389147405, 11, -1), be_const_func(be_neopixelbus_call_native) }, { be_nested_key("SK6812_GRBW", 81157857, 11, -1), be_const_int(4) }, - { be_nested_key("SK6812_GRB", 1159411308, 10, -1), be_const_int(3) }, - { be_nested_key("_p", 1594591802, 2, 5), be_const_var(0) }, + { be_nested_key("_t", 1527481326, 2, -1), be_const_var(1) }, + { be_nested_key("SK6812_GRB", 1159411308, 10, 1), be_const_int(3) }, })), - (be_nested_const_str("Leds_ntv", -292677248, 8)) + be_str_literal("Leds_ntv") ); /*******************************************************************/ diff --git a/lib/libesp32/Berry/default/embedded/leds.be b/lib/libesp32/Berry/default/embedded/leds.be index aed675125..289ad1118 100644 --- a/lib/libesp32/Berry/default/embedded/leds.be +++ b/lib/libesp32/Berry/default/embedded/leds.be @@ -126,16 +126,71 @@ class Leds : Leds_ntv end end +#- + +var s = Leds(25, gpio.pin(gpio.WS2812, 1)) +s.clear_to(0x300000) +s.show() +i = 0 + +def anim() + s.clear_to(0x300000) + s.set_pixel_color(i, 0x004000) + s.show() + i = (i + 1) % 25 + tasmota.set_timer(200, anim) +end +anim() + +-# + class Leds_matrix : Leds var h, w + var alternate # are rows in alternate mode (even/odd are reversed) def init(w, h, gpio, rmt) self.w = w self.h = h + self.alternate = false super(self).init(w * h, gpio, rmt) end + def set_alternate(alt) + self.alternate = alt + end + def get_alternate() + return self.alternate + end + def set_matrix_pixel_color(x, y, col, bri) - self.set_pixel_color(x * self.w + y, col, bri) + if self.alternate && x % 2 + # reversed line + self.set_pixel_color(x * self.w + self.h - y - 1, col, bri) + else + self.set_pixel_color(x * self.w + y, col, bri) + end end end + +#- + +var s = Leds_matrix(5, 5, gpio.pin(gpio.WS2812, 1)) +s.set_alternate(true) +s.clear_to(0x300000) +s.show() +x = 0 +y = 0 + +def anim() + s.clear_to(0x300000) + s.set_matrix_pixel_color(x, y, 0x004000) + s.show() + y = (y + 1) % 5 + if y == 0 + x = (x + 1) % 5 + end + tasmota.set_timer(200, anim) +end +anim() + +-# diff --git a/lib/libesp32/Berry/src/be_constobj.h b/lib/libesp32/Berry/src/be_constobj.h index d3f1f5764..87ab6eecf 100644 --- a/lib/libesp32/Berry/src/be_constobj.h +++ b/lib/libesp32/Berry/src/be_constobj.h @@ -234,6 +234,9 @@ const bntvmodule be_native_module(_module) = { \ BE_STRING \ } +#define be_str_literal(_str) \ + be_nested_const_str(_str, 0, sizeof(_str)-1 ) + #define be_nested_string(_str, _hash, _len) \ { \ { .s=(be_nested_const_str(_str, _hash, _len )) \ diff --git a/lib/libesp32/Berry/src/be_solidifylib.c b/lib/libesp32/Berry/src/be_solidifylib.c index 3dba26768..402db4547 100644 --- a/lib/libesp32/Berry/src/be_solidifylib.c +++ b/lib/libesp32/Berry/src/be_solidifylib.c @@ -351,7 +351,7 @@ static void m_solidify_subclass(bvm *vm, bclass *cl, int builtins) logfmt(" NULL,\n"); } - logfmt(" (be_nested_str_literal(\"%s\"))\n", class_name); + logfmt(" be_str_literal(\"%s\")\n", class_name); logfmt(");\n"); } diff --git a/tasmota/berry/leds/rainbow.be b/tasmota/berry/leds/rainbow.be index 03dcd1a86..bb7a4f105 100644 --- a/tasmota/berry/leds/rainbow.be +++ b/tasmota/berry/leds/rainbow.be @@ -79,7 +79,7 @@ r.start() -# -class Rainbow_Matrix : Leds_animator +class Rainbow_stripes : Leds_animator var cur_offset # current offset in the palette static palette = [ 0xFF0000, #- red -# 0xFFA500, #- orange -# @@ -111,8 +111,8 @@ class Rainbow_Matrix : Leds_animator var y = 0 while y < h var x = 0 + var col = palette[(cur_offset + y) % modulus] while x < w - var col = palette[(cur_offset + y) % modulus] set_matrix_pixel_color(strip, x, y, col, bri) # simulate the method call without GETMET x += 1 end From 86d94e6c0e0e155903c4b6ad178ceb050b890de6 Mon Sep 17 00:00:00 2001 From: Barbudor Date: Sun, 28 Nov 2021 16:25:24 +0100 Subject: [PATCH 136/185] remove minimal from BUILDS table --- BUILDS.md | 466 +++++++++++++++++++++++++++--------------------------- 1 file changed, 234 insertions(+), 232 deletions(-) diff --git a/BUILDS.md b/BUILDS.md index 483ac04c8..6b1c67e92 100644 --- a/BUILDS.md +++ b/BUILDS.md @@ -2,236 +2,238 @@ ESP8266 / ESP32 -m = minimal, l = lite, t = tasmota, k = knx, s = sensors, i = ir, d = display +l = lite, t = tasmota, k = knx, s = sensors, i = ir, d = display -| Feature or Sensor | m | l | t | k | s | i | d | Remarks -|-----------------------|---|---|-------|---|---|---|---|-------- -| MY_LANGUAGE en_GB | x | x | x / x | x | x | x | x | -| USE_UFILESYS | - | - | - / x | - | - | - | - | -| USE_ARDUINO_OTA | - | - | - / - | - | - | - | - | -| USE_DOMOTICZ | - | - | x / x | x | x | x | - | -| USE_HOME_ASSISTANT | - | - | x / x | x | x | x | - | -| USE_MQTT_TLS | - | - | - / - | - | - | - | - | -| USE_MQTT_TLS_CA_CERT | - | - | - / - | - | - | - | - | -| USE_MQTT_AWS_IOT | - | - | - / - | - | - | - | - | -| USE_4K_RSA | - | - | - / - | - | - | - | - | -| USE_TELEGRAM | - | - | - / - | - | - | - | - | -| USE_KNX | - | - | - / x | x | - | - | - | -| USE_WEBSERVER | x | x | x / x | x | x | x | x | -| USE_JAVASCRIPT_ES6 | - | - | - / - | - | - | - | - | -| USE_WEBSEND_RESPONSE | - | - | - / - | - | - | - | - | -| USE_EMULATION_HUE | - | x | x / x | - | x | - | - | -| USE_EMULATION_WEMO | - | x | x / x | - | x | - | - | -| USE_DISCOVERY | - | - | - / - | - | - | - | - | -| WEBSERVER_ADVERTISE | - | - | x / - | x | - | - | x | -| MQTT_HOST_DISCOVERY | - | - | - / - | - | - | - | - | -| USE_TIMERS | - | x | x / x | x | x | x | x | -| USE_TIMERS_WEB | - | x | x / x | x | x | x | x | -| USE_SUNRISE | - | x | x / x | x | x | x | x | -| USE_RULES | - | x | x / x | x | x | x | x | -| USE_SCRIPT | - | - | - / - | - | - | - | - | -| USE_EXPRESSION | - | - | - / - | - | - | - | - | -| SUPPORT_IF_STATEMENT | - | - | - / - | - | - | - | - | -| USE_HOTPLUG | - | - | - / - | - | - | - | - | -| USE_PROMETHEUS | - | - | - / - | - | - | - | - | -| USE_PING | - | - | - / - | - | - | - | - | -| | | | | | | | | -| Feature or Sensor | m | l | t | k | s | i | d | Remarks -| ROTARY_V1 | - | - | x / x | - | x | - | - | -| USE_SONOFF_RF | - | - | x / - | x | x | - | - | -| USE_RF_FLASH | - | - | x / - | x | x | - | - | -| USE_SONOFF_SC | - | - | x / - | x | x | - | - | -| USE_TUYA_MCU | - | x | x / - | x | x | - | x | -| USE_ARMTRONIX_DIMMERS | - | - | x / - | x | - | - | - | -| USE_PS_16_DZ | - | - | x / - | x | - | - | - | -| USE_SONOFF_IFAN | - | - | x / - | x | - | - | - | -| USE_BUZZER | - | - | x / x | x | x | - | - | -| USE_ARILUX_RF | - | - | x / - | x | - | - | - | -| USE_SHUTTER | - | - | x / x | x | - | - | - | -| USE_DEEPSLEEP | - | - | x / x | - | x | - | - | -| USE_EXS_DIMMER | - | - | x / - | x | - | - | - | -| USE_DEVICE_GROUPS | - | - | x / x | - | - | - | - | -| USE_PWM_DIMMER | - | - | x / - | x | - | - | - | -| USE_KEELOQ | - | - | - / - | - | - | - | - | -| USE_SONOFF_D1 | - | - | x / - | x | - | - | - | -| USE_SHELLY_DIMMER | - | - | x / - | - | - | - | - | -| USE_AC_ZERO_CROSS_DIMMER | - | - | x / x | x | x | x | x | -| | | | | | | | | -| Feature or Sensor | m | l | t | k | s | i | d | Remarks -| USE_LIGHT | - | x | x / x | x | x | x | x | -| USE_WS2812 | - | - | x / x | x | x | - | x | -| USE_WS2812_DMA | - | - | - / - | - | - | - | - | -| USE_MY92X1 | - | - | x / - | x | x | - | x | -| USE_SM16716 | - | - | x / - | x | x | - | x | -| USE_SM2135 | - | - | x / - | x | x | - | x | -| USE_SONOFF_L1 | - | - | x / - | x | x | - | x | -| USE_ELECTRIQ_MOODL | - | - | x / - | x | x | - | x | -| | | | | | | | | -| USE_ENERGY_SENSOR | - | x | x / x | x | x | - | - | -| USE_ENERGY_DUMMY | - | x | x / x | x | x | - | - | -| USE_PZEM004T | - | - | x / x | x | x | - | - | -| USE_PZEM_AC | - | - | x / x | x | x | - | - | -| USE_PZEM_DC | - | - | x / x | x | x | - | - | -| USE_MCP39F501 | - | x | x / - | x | x | - | - | -| USE_SDM72 | - | - | - / x | - | x | - | - | -| USE_SDM120 | - | - | - / x | - | x | - | - | -| USE_SDM630 | - | - | - / x | - | x | - | - | -| USE_DDS2382 | - | - | - / x | - | x | - | - | -| USE_DDSU666 | - | - | - / x | - | x | - | - | -| USE_SOLAX_X1 | - | - | - / - | - | - | - | - | -| USE_LE01MR | - | - | - / - | - | - | - | - | -| USE_BL09XX | - | x | x / x | x | x | - | - | -| USE_TELEINFO | - | - | - / - | - | - | - | - | -| USE_IEM3000 | - | - | - / - | - | - | - | - | -| USE_WE517 | - | - | - / - | - | - | - | - | -| | | | | | | | | -| USE_ADC_VCC | x | x | - / - | - | - | x | - | -| USE_COUNTER | - | - | x / x | x | x | - | x | -| USE_DS18x20 | - | - | x / x | x | x | - | x | -| USE_DHT | - | - | x / x | x | x | - | x | -| USE_MAX31855 | - | - | - / x | - | x | - | - | -| USE_MAX31865 | - | - | - / - | - | - | - | - | -| USE_THERMOSTAT | - | - | - / - | - | - | - | - | -| USE_LMT01 | - | - | - / x | - | x | - | - | -| | | | | | | | | -| Feature or Sensor | m | l | t | k | s | i | d | Remarks -| USE_I2C | - | - | x / x | x | x | - | x | -| USE_SHT | - | - | - / x | - | x | - | - | -| USE_HTU | - | - | - / x | - | x | - | - | -| USE_BMP | - | - | - / x | - | x | - | - | -| USE_BME680 | - | - | - / x | - | x | - | - | -| USE_BH1750 | - | - | - / x | - | x | - | - | -| USE_VEML6070 | - | - | - / x | - | x | - | - | -| USE_ADS1115 | - | - | - / x | - | x | - | - | -| USE_INA219 | - | - | - / x | - | x | - | - | -| USE_INA226 | - | - | - / - | - | - | - | - | -| USE_SHT3X | - | - | - / x | - | x | - | - | -| USE_TSL2561 | - | - | - / - | - | - | - | - | -| USE_TSL2591 | - | - | - / - | - | - | - | - | -| USE_MGS | - | - | - / x | - | x | - | - | -| USE_SGP30 | - | - | - / x | - | x | - | - | -| USE_SI1145 | - | - | - / - | - | - | - | - | -| USE_LM75AD | - | - | - / x | - | x | - | - | -| USE_APDS9960 | - | - | - / - | - | - | - | - | -| USE_MCP230xx | - | - | - / - | - | - | - | - | -| USE_PCA9685 | - | - | - / - | - | - | - | - | -| USE_MPR121 | - | - | - / - | - | - | - | - | -| USE_CCS811 | - | - | - / - | - | x | - | - | -| USE_CCS811_V2 | - | - | - / x | - | - | - | - | -| USE_MPU6050 | - | - | - / - | - | - | - | - | -| USE_DS3231 | - | - | - / - | - | - | - | - | -| USE_MGC3130 | - | - | - / - | - | - | - | - | -| USE_MAX44009 | - | - | - / - | - | - | - | - | -| USE_SCD30 | - | - | - / x | - | x | - | - | -| USE_SCD40 | - | - | - / x | - | - | - | - | -| USE_SPS30 | - | - | - / - | - | - | - | - | -| USE_ADE7953 | - | - | x / x | x | x | - | x | -| USE_VL53L0X | - | - | - / x | - | x | - | - | -| USE_MLX90614 | - | - | - / - | - | - | - | - | -| USE_CHIRP | - | - | - / - | - | - | - | - | -| USE_PAJ7620 | - | - | - / - | - | - | - | - | -| USE_PCF8574 | - | - | - / - | - | - | - | - | -| | | | | | | | | -| Feature or Sensor | m | l | t | k | s | i | d | Remarks -| USE_HIH6 | - | - | - / x | - | x | - | - | -| USE_DHT12 | - | - | - / x | - | x | - | - | -| USE_DS1624 | - | - | - / x | - | x | - | - | -| USE_AHT1x | - | - | - / - | - | - | - | - | -| USE_HDC1080 | - | - | - / - | - | - | - | - | -| USE_WEMOS_MOTOR_V1 | - | - | - / x | - | x | - | - | -| USE_IAQ | - | - | - / x | - | x | - | - | -| USE_AS3935 | - | - | - / x | - | x | - | - | -| USE_VEML6075 | - | - | - / - | - | - | - | - | -| USE_VEML7700 | - | - | - / - | - | - | - | - | -| USE_MCP9808 | - | - | - / - | - | - | - | - | -| USE_HP303B | - | - | - / - | - | - | - | - | -| USE_EZOCO2 | - | - | - / - | - | - | - | - | -| USE_EZODO | - | - | - / - | - | - | - | - | -| USE_EZOEC | - | - | - / - | - | - | - | - | -| USE_EZOFLO | - | - | - / - | - | - | - | - | -| USE_EZOHUM | - | - | - / - | - | - | - | - | -| USE_EZOO2 | - | - | - / - | - | - | - | - | -| USE_EZOORP | - | - | - / - | - | - | - | - | -| USE_EZOPH | - | - | - / - | - | - | - | - | -| USE_EZOPMP | - | - | - / - | - | - | - | - | -| USE_EZOPRS | - | - | - / - | - | - | - | - | -| USE_EZORGB | - | - | - / - | - | - | - | - | -| USE_EZORTD | - | - | - / - | - | - | - | - | -| USE_SEESAW_SOIL | - | - | - / - | - | - | - | - | -| USE_TOF10120 | - | - | - / - | - | - | - | - | -| USE_AM2320 | - | - | - / - | - | - | - | - | -| USE_T67XX | - | - | - / - | - | - | - | - | -| USE_HM330X | - | - | - / - | - | - | - | - | -| | | | | | | | | -| Feature or Sensor | m | l | t | k | s | i | d | Remarks -| USE_SPI | - | - | - / - | - | - | - | x | -| USE_RC522 | - | - | - / - | - | - | - | - | -| USE_MHZ19 | - | - | - / x | - | x | - | - | -| USE_SENSEAIR | - | - | - / x | - | x | - | - | -| USE_PMS5003 | - | - | - / x | - | x | - | - | -| USE_NOVA_SDS | - | - | - / x | - | x | - | - | -| USE_HPMA | - | - | - / x | - | x | - | - | -| USE_SERIAL_BRIDGE | - | - | x / x | x | x | - | x | -| USE_MP3_PLAYER | - | - | - / x | - | x | - | - | -| USE_AZ7798 | - | - | - / - | - | - | - | - | -| USE_PN532_HSU | - | - | - / x | - | x | - | - | -| USE_RDM6300 | - | - | - / x | - | x | - | - | -| USE_IBEACON | - | - | - / x | - | x | - | - | -| USE_GPS | - | - | - / - | - | - | - | - | -| USE_HM10 | - | - | - / - | - | x | - | - | -| USE_HRXL | - | - | - / x | - | x | - | - | -| USE_TASMOTA_CLIENT | - | - | - / - | - | - | - | - | -| USE_OPENTHERM | - | - | - / - | - | - | - | - | -| USE_MIEL_HVAC | - | - | - / - | - | - | - | - | -| USE_PROJECTOR_CTRL | - | - | - / - | - | - | - | - | -| USE_AS608 | - | - | - / - | - | - | - | - | -| USE_TCP_BRIDGE | - | - | - / - | - | - | - | - | zbbridge -| | | | | | | | | -| USE_NRF24 | - | - | - / - | - | - | - | - | -| USE_MIBLE | - | - | - / - | - | - | - | - | -| USE_ZIGBEE | - | - | - / - | - | - | - | - | -| USE_ZIGBEE_ZNP | - | - | - / - | - | - | - | - | -| USE_ZIGBEE_EZSP | - | - | - / - | - | - | - | - | Sonoff ZbBridge -| | | | | | | | | -| USE_IR_REMOTE | - | - | x / - | x | x | x | x | -| USE_IR_RECEIVE | - | - | x / - | x | x | x | x | -| USE_IR_REMOTE_FULL | - | - | - / - | - | - | x | - | Enable ALL protocols -| | | | | | | | | -| USE_SR04 | - | - | - / - | - | x | - | - | -| USE_DYP | - | - | - / - | - | - | - | - | -| USE_TM1638 | - | - | - / x | - | x | - | - | -| USE_HX711 | - | - | - / x | - | x | - | - | -| USE_TX2x_WIND_SENSOR | - | - | - / - | - | - | - | - | -| USE_WINDMETER | - | - | - / - | - | - | - | - | -| USE_RC_SWITCH | - | - | - / x | - | x | - | - | -| USE_RF_SENSOR | - | - | - / x | - | x | - | - | AlectoV2 only -| USE_HRE | - | - | - / x | - | x | - | - | -| USE_A4988_STEPPER | - | - | - / - | - | - | - | - | -| USE_NEOPOOL | - | - | - / - | - | - | - | - | -| | | | | | | | | -| Feature or Sensor | m | l | t | k | s | i | d | Remarks -| USE_DISPLAY | - | - | - / - | - | - | - | x | -| USE_DISPLAY_LCD | - | - | - / - | - | - | - | x | -| USE_DISPLAY_SSD1306 | - | - | - / - | - | - | - | x | -| USE_DISPLAY_MATRIX | - | - | - / - | - | - | - | x | -| USE_DISPLAY_SH1106 | - | - | - / - | - | - | - | x | -| USE_DISPLAY_ILI9341 | - | - | - / - | - | - | - | x | -| USE_DISPLAY_EPAPER_29 | - | - | - / - | - | - | - | x | -| USE_DISPLAY_EPAPER_42 | - | - | - / - | - | - | - | x | -| USE_DISPLAY_SSD1351 | - | - | - / - | - | - | - | x | -| USE_DISPLAY_RA8876 | - | - | - / - | - | - | - | x | -| USE_DISPLAY_ST7789 | - | - | - / - | - | - | - | x | -| USE_DISPLAY_TM1637 | - | - | - / - | - | - | - | x | -| | | | | | | | | -| USE_FT5206 | - | - | - / - | - | - | - | - | -| USE_FTC532 | - | - | - / - | - | - | - | - | -| USE_BS814A2 | - | - | - / - | - | - | - | - | -| | | | | | | | | -| ESP32 Feature | m | l | t | k | s | i | d | Remarks -| USE_HALLEFFECT | | | / x | | | | | -| USE_MI_ESP32 | | | / x | | | | | See SetOption115 -| USE_IBEACON_ESP32 | | | / - | | | | | -| USE_WEBCAM | | | / - | | | | | -| USE_ETHERNET | | | / - | | | | | -| USE_I2S_AUDIO | | | / - | | | | | -| USE_TTGO_WATCH | | | / - | | | | | +Note: `minimal` variant is not listed as t shouldn't be used outside of the [upgrading](https://tasmota.github.io/docs/Upgrading/) process. + +| Feature or Sensor | l | t | k | s | i | d | Remarks +|-----------------------|---|-------|---|---|---|---|-------- +| MY_LANGUAGE en_GB | x | x / x | x | x | x | x | +| USE_UFILESYS | - | - / x | - | - | - | - | +| USE_ARDUINO_OTA | - | - / - | - | - | - | - | +| USE_DOMOTICZ | - | x / x | x | x | x | - | +| USE_HOME_ASSISTANT | - | x / x | x | x | x | - | +| USE_MQTT_TLS | - | - / - | - | - | - | - | +| USE_MQTT_TLS_CA_CERT | - | - / - | - | - | - | - | +| USE_MQTT_AWS_IOT | - | - / - | - | - | - | - | +| USE_4K_RSA | - | - / - | - | - | - | - | +| USE_TELEGRAM | - | - / - | - | - | - | - | +| USE_KNX | - | - / x | x | - | - | - | +| USE_WEBSERVER | x | x / x | x | x | x | x | +| USE_JAVASCRIPT_ES6 | - | - / - | - | - | - | - | +| USE_WEBSEND_RESPONSE | - | - / - | - | - | - | - | +| USE_EMULATION_HUE | x | x / x | - | x | - | - | +| USE_EMULATION_WEMO | x | x / x | - | x | - | - | +| USE_DISCOVERY | - | - / - | - | - | - | - | +| WEBSERVER_ADVERTISE | - | x / - | x | - | - | x | +| MQTT_HOST_DISCOVERY | - | - / - | - | - | - | - | +| USE_TIMERS | x | x / x | x | x | x | x | +| USE_TIMERS_WEB | x | x / x | x | x | x | x | +| USE_SUNRISE | x | x / x | x | x | x | x | +| USE_RULES | x | x / x | x | x | x | x | +| USE_SCRIPT | - | - / - | - | - | - | - | +| USE_EXPRESSION | - | - / - | - | - | - | - | +| SUPPORT_IF_STATEMENT | - | - / - | - | - | - | - | +| USE_HOTPLUG | - | - / - | - | - | - | - | +| USE_PROMETHEUS | - | - / - | - | - | - | - | +| USE_PING | - | - / - | - | - | - | - | +| | | | | | | | +| Feature or Sensor | l | t | k | s | i | d | Remarks +| ROTARY_V1 | - | x / x | - | x | - | - | +| USE_SONOFF_RF | - | x / - | x | x | - | - | +| USE_RF_FLASH | - | x / - | x | x | - | - | +| USE_SONOFF_SC | - | x / - | x | x | - | - | +| USE_TUYA_MCU | x | x / - | x | x | - | x | +| USE_ARMTRONIX_DIMMERS | - | x / - | x | - | - | - | +| USE_PS_16_DZ | - | x / - | x | - | - | - | +| USE_SONOFF_IFAN | - | x / - | x | - | - | - | +| USE_BUZZER | - | x / x | x | x | - | - | +| USE_ARILUX_RF | - | x / - | x | - | - | - | +| USE_SHUTTER | - | x / x | x | - | - | - | +| USE_DEEPSLEEP | - | x / x | - | x | - | - | +| USE_EXS_DIMMER | - | x / - | x | - | - | - | +| USE_DEVICE_GROUPS | - | x / x | - | - | - | - | +| USE_PWM_DIMMER | - | x / - | x | - | - | - | +| USE_KEELOQ | - | - / - | - | - | - | - | +| USE_SONOFF_D1 | - | x / - | x | - | - | - | +| USE_SHELLY_DIMMER | - | x / - | - | - | - | - | +| USE_AC_ZERO_CROSS_DIMMER | - | x / x | x | x | x | x | +| | | | | | | | +| Feature or Sensor | l | t | k | s | i | d | Remarks +| USE_LIGHT | x | x / x | x | x | x | x | +| USE_WS2812 | - | x / x | x | x | - | x | +| USE_WS2812_DMA | - | - / - | - | - | - | - | +| USE_MY92X1 | - | x / - | x | x | - | x | +| USE_SM16716 | - | x / - | x | x | - | x | +| USE_SM2135 | - | x / - | x | x | - | x | +| USE_SONOFF_L1 | - | x / - | x | x | - | x | +| USE_ELECTRIQ_MOODL | - | x / - | x | x | - | x | +| | | | | | | | +| USE_ENERGY_SENSOR | x | x / x | x | x | - | - | +| USE_ENERGY_DUMMY | x | x / x | x | x | - | - | +| USE_PZEM004T | - | x / x | x | x | - | - | +| USE_PZEM_AC | - | x / x | x | x | - | - | +| USE_PZEM_DC | - | x / x | x | x | - | - | +| USE_MCP39F501 | x | x / - | x | x | - | - | +| USE_SDM72 | - | - / x | - | x | - | - | +| USE_SDM120 | - | - / x | - | x | - | - | +| USE_SDM630 | - | - / x | - | x | - | - | +| USE_DDS2382 | - | - / x | - | x | - | - | +| USE_DDSU666 | - | - / x | - | x | - | - | +| USE_SOLAX_X1 | - | - / - | - | - | - | - | +| USE_LE01MR | - | - / - | - | - | - | - | +| USE_BL09XX | x | x / x | x | x | - | - | +| USE_TELEINFO | - | - / - | - | - | - | - | +| USE_IEM3000 | - | - / - | - | - | - | - | +| USE_WE517 | - | - / - | - | - | - | - | +| | | | | | | | +| USE_ADC_VCC | x | - / - | - | - | x | - | +| USE_COUNTER | - | x / x | x | x | - | x | +| USE_DS18x20 | - | x / x | x | x | - | x | +| USE_DHT | - | x / x | x | x | - | x | +| USE_MAX31855 | - | - / x | - | x | - | - | +| USE_MAX31865 | - | - / - | - | - | - | - | +| USE_THERMOSTAT | - | - / - | - | - | - | - | +| USE_LMT01 | - | - / x | - | x | - | - | +| | | | | | | | +| Feature or Sensor | l | t | k | s | i | d | Remarks +| USE_I2C | - | x / x | x | x | - | x | +| USE_SHT | - | - / x | - | x | - | - | +| USE_HTU | - | - / x | - | x | - | - | +| USE_BMP | - | - / x | - | x | - | - | +| USE_BME680 | - | - / x | - | x | - | - | +| USE_BH1750 | - | - / x | - | x | - | - | +| USE_VEML6070 | - | - / x | - | x | - | - | +| USE_ADS1115 | - | - / x | - | x | - | - | +| USE_INA219 | - | - / x | - | x | - | - | +| USE_INA226 | - | - / - | - | - | - | - | +| USE_SHT3X | - | - / x | - | x | - | - | +| USE_TSL2561 | - | - / - | - | - | - | - | +| USE_TSL2591 | - | - / - | - | - | - | - | +| USE_MGS | - | - / x | - | x | - | - | +| USE_SGP30 | - | - / x | - | x | - | - | +| USE_SI1145 | - | - / - | - | - | - | - | +| USE_LM75AD | - | - / x | - | x | - | - | +| USE_APDS9960 | - | - / - | - | - | - | - | +| USE_MCP230xx | - | - / - | - | - | - | - | +| USE_PCA9685 | - | - / - | - | - | - | - | +| USE_MPR121 | - | - / - | - | - | - | - | +| USE_CCS811 | - | - / - | - | x | - | - | +| USE_CCS811_V2 | - | - / x | - | - | - | - | +| USE_MPU6050 | - | - / - | - | - | - | - | +| USE_DS3231 | - | - / - | - | - | - | - | +| USE_MGC3130 | - | - / - | - | - | - | - | +| USE_MAX44009 | - | - / - | - | - | - | - | +| USE_SCD30 | - | - / x | - | x | - | - | +| USE_SCD40 | - | - / x | - | - | - | - | +| USE_SPS30 | - | - / - | - | - | - | - | +| USE_ADE7953 | - | x / x | x | x | - | x | +| USE_VL53L0X | - | - / x | - | x | - | - | +| USE_MLX90614 | - | - / - | - | - | - | - | +| USE_CHIRP | - | - / - | - | - | - | - | +| USE_PAJ7620 | - | - / - | - | - | - | - | +| USE_PCF8574 | - | - / - | - | - | - | - | +| | | | | | | | +| Feature or Sensor | l | t | k | s | i | d | Remarks +| USE_HIH6 | - | - / x | - | x | - | - | +| USE_DHT12 | - | - / x | - | x | - | - | +| USE_DS1624 | - | - / x | - | x | - | - | +| USE_AHT1x | - | - / - | - | - | - | - | +| USE_HDC1080 | - | - / - | - | - | - | - | +| USE_WEMOS_MOTOR_V1 | - | - / x | - | x | - | - | +| USE_IAQ | - | - / x | - | x | - | - | +| USE_AS3935 | - | - / x | - | x | - | - | +| USE_VEML6075 | - | - / - | - | - | - | - | +| USE_VEML7700 | - | - / - | - | - | - | - | +| USE_MCP9808 | - | - / - | - | - | - | - | +| USE_HP303B | - | - / - | - | - | - | - | +| USE_EZOCO2 | - | - / - | - | - | - | - | +| USE_EZODO | - | - / - | - | - | - | - | +| USE_EZOEC | - | - / - | - | - | - | - | +| USE_EZOFLO | - | - / - | - | - | - | - | +| USE_EZOHUM | - | - / - | - | - | - | - | +| USE_EZOO2 | - | - / - | - | - | - | - | +| USE_EZOORP | - | - / - | - | - | - | - | +| USE_EZOPH | - | - / - | - | - | - | - | +| USE_EZOPMP | - | - / - | - | - | - | - | +| USE_EZOPRS | - | - / - | - | - | - | - | +| USE_EZORGB | - | - / - | - | - | - | - | +| USE_EZORTD | - | - / - | - | - | - | - | +| USE_SEESAW_SOIL | - | - / - | - | - | - | - | +| USE_TOF10120 | - | - / - | - | - | - | - | +| USE_AM2320 | - | - / - | - | - | - | - | +| USE_T67XX | - | - / - | - | - | - | - | +| USE_HM330X | - | - / - | - | - | - | - | +| | | | | | | | +| Feature or Sensor | l | t | k | s | i | d | Remarks +| USE_SPI | - | - / - | - | - | - | x | +| USE_RC522 | - | - / - | - | - | - | - | +| USE_MHZ19 | - | - / x | - | x | - | - | +| USE_SENSEAIR | - | - / x | - | x | - | - | +| USE_PMS5003 | - | - / x | - | x | - | - | +| USE_NOVA_SDS | - | - / x | - | x | - | - | +| USE_HPMA | - | - / x | - | x | - | - | +| USE_SERIAL_BRIDGE | - | x / x | x | x | - | x | +| USE_MP3_PLAYER | - | - / x | - | x | - | - | +| USE_AZ7798 | - | - / - | - | - | - | - | +| USE_PN532_HSU | - | - / x | - | x | - | - | +| USE_RDM6300 | - | - / x | - | x | - | - | +| USE_IBEACON | - | - / x | - | x | - | - | +| USE_GPS | - | - / - | - | - | - | - | +| USE_HM10 | - | - / - | - | x | - | - | +| USE_HRXL | - | - / x | - | x | - | - | +| USE_TASMOTA_CLIENT | - | - / - | - | - | - | - | +| USE_OPENTHERM | - | - / - | - | - | - | - | +| USE_MIEL_HVAC | - | - / - | - | - | - | - | +| USE_PROJECTOR_CTRL | - | - / - | - | - | - | - | +| USE_AS608 | - | - / - | - | - | - | - | +| USE_TCP_BRIDGE | - | - / - | - | - | - | - | zbbridge +| | | | | | | | +| USE_NRF24 | - | - / - | - | - | - | - | +| USE_MIBLE | - | - / - | - | - | - | - | +| USE_ZIGBEE | - | - / - | - | - | - | - | +| USE_ZIGBEE_ZNP | - | - / - | - | - | - | - | +| USE_ZIGBEE_EZSP | - | - / - | - | - | - | - | Sonoff ZbBridge +| | | | | | | | +| USE_IR_REMOTE | - | x / - | x | x | x | x | +| USE_IR_RECEIVE | - | x / - | x | x | x | x | +| USE_IR_REMOTE_FULL | - | - / - | - | - | x | - | Enable ALL protocols +| | | | | | | | +| USE_SR04 | - | - / - | - | x | - | - | +| USE_DYP | - | - / - | - | - | - | - | +| USE_TM1638 | - | - / x | - | x | - | - | +| USE_HX711 | - | - / x | - | x | - | - | +| USE_TX2x_WIND_SENSOR | - | - / - | - | - | - | - | +| USE_WINDMETER | - | - / - | - | - | - | - | +| USE_RC_SWITCH | - | - / x | - | x | - | - | +| USE_RF_SENSOR | - | - / x | - | x | - | - | AlectoV2 only +| USE_HRE | - | - / x | - | x | - | - | +| USE_A4988_STEPPER | - | - / - | - | - | - | - | +| USE_NEOPOOL | - | - / - | - | - | - | - | +| | | | | | | | +| Feature or Sensor | l | t | k | s | i | d | Remarks +| USE_DISPLAY | - | - / - | - | - | - | x | +| USE_DISPLAY_LCD | - | - / - | - | - | - | x | +| USE_DISPLAY_SSD1306 | - | - / - | - | - | - | x | +| USE_DISPLAY_MATRIX | - | - / - | - | - | - | x | +| USE_DISPLAY_SH1106 | - | - / - | - | - | - | x | +| USE_DISPLAY_ILI9341 | - | - / - | - | - | - | x | +| USE_DISPLAY_EPAPER_29 | - | - / - | - | - | - | x | +| USE_DISPLAY_EPAPER_42 | - | - / - | - | - | - | x | +| USE_DISPLAY_SSD1351 | - | - / - | - | - | - | x | +| USE_DISPLAY_RA8876 | - | - / - | - | - | - | x | +| USE_DISPLAY_ST7789 | - | - / - | - | - | - | x | +| USE_DISPLAY_TM1637 | - | - / - | - | - | - | x | +| | | | | | | | +| USE_FT5206 | - | - / - | - | - | - | - | +| USE_FTC532 | - | - / - | - | - | - | - | +| USE_BS814A2 | - | - / - | - | - | - | - | +| | | | | | | | +| ESP32 Feature | l | t | k | s | i | d | Remarks +| USE_HALLEFFECT | | / x | | | | | +| USE_MI_ESP32 | | / x | | | | | See SetOption115 +| USE_IBEACON_ESP32 | | / - | | | | | +| USE_WEBCAM | | / - | | | | | +| USE_ETHERNET | | / - | | | | | +| USE_I2S_AUDIO | | / - | | | | | +| USE_TTGO_WATCH | | / - | | | | | From e84e4ea8a31048ece5cb7e2a72ad06010d673567 Mon Sep 17 00:00:00 2001 From: Barbudor Date: Sun, 28 Nov 2021 16:40:00 +0100 Subject: [PATCH 137/185] fix typo --- BUILDS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILDS.md b/BUILDS.md index 6b1c67e92..228de677f 100644 --- a/BUILDS.md +++ b/BUILDS.md @@ -4,7 +4,7 @@ ESP8266 / ESP32 l = lite, t = tasmota, k = knx, s = sensors, i = ir, d = display -Note: `minimal` variant is not listed as t shouldn't be used outside of the [upgrading](https://tasmota.github.io/docs/Upgrading/) process. +Note: `minimal` variant is not listed as it shouldn't be used outside of the [upgrading](https://tasmota.github.io/docs/Upgrading/) process. | Feature or Sensor | l | t | k | s | i | d | Remarks |-----------------------|---|-------|---|---|---|---|-------- From b4cbeac2151222b7e535e0cd4bf04da7df7a6e6f Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sun, 28 Nov 2021 18:10:18 +0100 Subject: [PATCH 138/185] Berry avoid LittleFS issue with persist --- lib/libesp32/Berry/default/be_persist_lib.c | 198 +++++++++--------- .../Berry/default/embedded/persist.be | 2 + tasmota/xdrv_52_7_berry_embedded.ino | 2 - 3 files changed, 103 insertions(+), 99 deletions(-) diff --git a/lib/libesp32/Berry/default/be_persist_lib.c b/lib/libesp32/Berry/default/be_persist_lib.c index e0a92dcd9..4684283d4 100644 --- a/lib/libesp32/Berry/default/be_persist_lib.c +++ b/lib/libesp32/Berry/default/be_persist_lib.c @@ -10,7 +10,7 @@ /******************************************************************** ** Solidified function: json_fdump_map ********************************************************************/ -be_local_closure(json_fdump_map, /* name */ +be_local_closure(Persist_json_fdump_map, /* name */ be_nested_proto( 13, /* nstack */ 3, /* argc */ @@ -21,16 +21,16 @@ be_local_closure(json_fdump_map, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[10]) { /* constants */ - /* K0 */ be_nested_string("json", 916562499, 4), - /* K1 */ be_nested_string("write", -1104765092, 5), - /* K2 */ be_nested_string("{", -32746982, 1), - /* K3 */ be_nested_string("keys", -112588595, 4), - /* K4 */ be_nested_string("dump", -631966073, 4), - /* K5 */ be_nested_string(":", 1057798253, 1), - /* K6 */ be_nested_string("json_fdump_any", -946337911, 14), - /* K7 */ be_nested_string(",", 688690635, 1), - /* K8 */ be_nested_string("stop_iteration", -121173395, 14), - /* K9 */ be_nested_string("}", -133412696, 1), + /* K0 */ be_nested_str_literal("json"), + /* K1 */ be_nested_str_literal("write"), + /* K2 */ be_nested_str_literal("{"), + /* K3 */ be_nested_str_literal("keys"), + /* K4 */ be_nested_str_literal("dump"), + /* K5 */ be_nested_str_literal(":"), + /* K6 */ be_nested_str_literal("json_fdump_any"), + /* K7 */ be_nested_str_literal(","), + /* K8 */ be_nested_str_literal("stop_iteration"), + /* K9 */ be_nested_str_literal("}"), }), (be_nested_const_str("json_fdump_map", -203012643, 14)), ((bstring*) &be_const_str_input), @@ -85,7 +85,7 @@ be_local_closure(json_fdump_map, /* name */ /******************************************************************** ** Solidified function: setmember ********************************************************************/ -be_local_closure(setmember, /* name */ +be_local_closure(Persist_setmember, /* name */ be_nested_proto( 4, /* nstack */ 3, /* argc */ @@ -96,8 +96,8 @@ be_local_closure(setmember, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_string("_p", 1594591802, 2), - /* K1 */ be_nested_string("_dirty", 283846766, 6), + /* K0 */ be_nested_str_literal("_p"), + /* K1 */ be_nested_str_literal("_dirty"), }), (be_nested_const_str("setmember", 1432909441, 9)), ((bstring*) &be_const_str_input), @@ -116,7 +116,7 @@ be_local_closure(setmember, /* name */ /******************************************************************** ** Solidified function: zero ********************************************************************/ -be_local_closure(zero, /* name */ +be_local_closure(Persist_zero, /* name */ be_nested_proto( 2, /* nstack */ 1, /* argc */ @@ -127,8 +127,8 @@ be_local_closure(zero, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_string("_p", 1594591802, 2), - /* K1 */ be_nested_string("_dirty", 283846766, 6), + /* K0 */ be_nested_str_literal("_p"), + /* K1 */ be_nested_str_literal("_dirty"), }), (be_nested_const_str("zero", -1955600541, 4)), ((bstring*) &be_const_str_input), @@ -148,7 +148,7 @@ be_local_closure(zero, /* name */ /******************************************************************** ** Solidified function: member ********************************************************************/ -be_local_closure(member, /* name */ +be_local_closure(Persist_member, /* name */ be_nested_proto( 5, /* nstack */ 2, /* argc */ @@ -159,8 +159,8 @@ be_local_closure(member, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_string("_p", 1594591802, 2), - /* K1 */ be_nested_string("find", -1108310694, 4), + /* K0 */ be_nested_str_literal("_p"), + /* K1 */ be_nested_str_literal("find"), }), (be_nested_const_str("member", 719708611, 6)), ((bstring*) &be_const_str_input), @@ -179,7 +179,7 @@ be_local_closure(member, /* name */ /******************************************************************** ** Solidified function: json_fdump ********************************************************************/ -be_local_closure(json_fdump, /* name */ +be_local_closure(Persist_json_fdump, /* name */ be_nested_proto( 7, /* nstack */ 2, /* argc */ @@ -190,11 +190,11 @@ be_local_closure(json_fdump, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_string("json", 916562499, 4), - /* K1 */ be_nested_string("_p", 1594591802, 2), - /* K2 */ be_nested_string("json_fdump_map", -203012643, 14), - /* K3 */ be_nested_string("internal_error", -1775809127, 14), - /* K4 */ be_nested_string("persist._p is not a map", 1176528732, 23), + /* K0 */ be_nested_str_literal("json"), + /* K1 */ be_nested_str_literal("_p"), + /* K2 */ be_nested_str_literal("json_fdump_map"), + /* K3 */ be_nested_str_literal("internal_error"), + /* K4 */ be_nested_str_literal("persist._p is not a map"), }), (be_nested_const_str("json_fdump", 1694216580, 10)), ((bstring*) &be_const_str_input), @@ -221,7 +221,7 @@ be_local_closure(json_fdump, /* name */ /******************************************************************** ** Solidified function: remove ********************************************************************/ -be_local_closure(remove, /* name */ +be_local_closure(Persist_remove, /* name */ be_nested_proto( 5, /* nstack */ 2, /* argc */ @@ -232,9 +232,9 @@ be_local_closure(remove, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_string("_p", 1594591802, 2), - /* K1 */ be_nested_string("remove", -611183107, 6), - /* K2 */ be_nested_string("_dirty", 283846766, 6), + /* K0 */ be_nested_str_literal("_p"), + /* K1 */ be_nested_str_literal("remove"), + /* K2 */ be_nested_str_literal("_dirty"), }), (be_nested_const_str("remove", -611183107, 6)), ((bstring*) &be_const_str_input), @@ -255,7 +255,7 @@ be_local_closure(remove, /* name */ /******************************************************************** ** Solidified function: json_fdump_any ********************************************************************/ -be_local_closure(json_fdump_any, /* name */ +be_local_closure(Persist_json_fdump_any, /* name */ be_nested_proto( 9, /* nstack */ 3, /* argc */ @@ -266,11 +266,11 @@ be_local_closure(json_fdump_any, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_string("json", 916562499, 4), - /* K1 */ be_nested_string("json_fdump_map", -203012643, 14), - /* K2 */ be_nested_string("json_fdump_list", -391087443, 15), - /* K3 */ be_nested_string("write", -1104765092, 5), - /* K4 */ be_nested_string("dump", -631966073, 4), + /* K0 */ be_nested_str_literal("json"), + /* K1 */ be_nested_str_literal("json_fdump_map"), + /* K2 */ be_nested_str_literal("json_fdump_list"), + /* K3 */ be_nested_str_literal("write"), + /* K4 */ be_nested_str_literal("dump"), }), (be_nested_const_str("json_fdump_any", -946337911, 14)), ((bstring*) &be_const_str_input), @@ -311,7 +311,7 @@ be_local_closure(json_fdump_any, /* name */ /******************************************************************** ** Solidified function: save ********************************************************************/ -be_local_closure(save, /* name */ +be_local_closure(Persist_save, /* name */ be_nested_proto( 7, /* nstack */ 1, /* argc */ @@ -322,13 +322,13 @@ be_local_closure(save, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 7]) { /* constants */ - /* K0 */ be_nested_string("_filename", 1430813195, 9), - /* K1 */ be_nested_string("w", -234078410, 1), - /* K2 */ be_nested_string("json_fdump", 1694216580, 10), - /* K3 */ be_nested_string("close", 667630371, 5), - /* K4 */ be_nested_string("write", -1104765092, 5), - /* K5 */ be_nested_string("{}", 1415952421, 2), - /* K6 */ be_nested_string("_dirty", 283846766, 6), + /* K0 */ be_nested_str_literal("_filename"), + /* K1 */ be_nested_str_literal("w"), + /* K2 */ be_nested_str_literal("json_fdump"), + /* K3 */ be_nested_str_literal("close"), + /* K4 */ be_nested_str_literal("write"), + /* K5 */ be_nested_str_literal("{}"), + /* K6 */ be_nested_str_literal("_dirty"), }), (be_nested_const_str("save", -855671224, 4)), ((bstring*) &be_const_str_input), @@ -379,7 +379,7 @@ be_local_closure(save, /* name */ /******************************************************************** ** Solidified function: load ********************************************************************/ -be_local_closure(load, /* name */ +be_local_closure(Persist_load, /* name */ be_nested_proto( 9, /* nstack */ 1, /* argc */ @@ -389,22 +389,23 @@ be_local_closure(load, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[11]) { /* constants */ - /* K0 */ be_nested_string("json", 916562499, 4), - /* K1 */ be_nested_string("path", -2071507658, 4), - /* K2 */ be_nested_string("exists", 1002329533, 6), - /* K3 */ be_nested_string("_filename", 1430813195, 9), - /* K4 */ be_nested_string("r", -150190315, 1), - /* K5 */ be_nested_string("load", -435725847, 4), - /* K6 */ be_nested_string("read", -824204347, 4), - /* K7 */ be_nested_string("close", 667630371, 5), - /* K8 */ be_nested_string("_p", 1594591802, 2), - /* K9 */ be_nested_string("BRY: failed to load _persist.json", -1303053851, 33), - /* K10 */ be_nested_string("_dirty", 283846766, 6), + ( &(const bvalue[12]) { /* constants */ + /* K0 */ be_nested_str_literal("json"), + /* K1 */ be_nested_str_literal("path"), + /* K2 */ be_nested_str_literal("exists"), + /* K3 */ be_nested_str_literal("_filename"), + /* K4 */ be_nested_str_literal("r"), + /* K5 */ be_nested_str_literal("load"), + /* K6 */ be_nested_str_literal("read"), + /* K7 */ be_nested_str_literal("close"), + /* K8 */ be_nested_str_literal("_p"), + /* K9 */ be_nested_str_literal("BRY: failed to load _persist.json"), + /* K10 */ be_nested_str_literal("_dirty"), + /* K11 */ be_nested_str_literal("save"), }), (be_nested_const_str("load", -435725847, 4)), ((bstring*) &be_const_str_input), - ( &(const binstruction[46]) { /* code */ + ( &(const binstruction[49]) { /* code */ 0xA4060000, // 0000 IMPORT R1 K0 0xA40A0200, // 0001 IMPORT R2 K1 0x4C0C0000, // 0002 LDNIL R3 @@ -412,7 +413,7 @@ be_local_closure(load, /* name */ 0x8C140502, // 0004 GETMET R5 R2 K2 0x881C0103, // 0005 GETMBR R7 R0 K3 0x7C140400, // 0006 CALL R5 2 - 0x78160024, // 0007 JMPF R5 #002D + 0x78160025, // 0007 JMPF R5 #002E 0xA802000D, // 0008 EXBLK 0 #0017 0x60140011, // 0009 GETGBL R5 G17 0x88180103, // 000A GETMBR R6 R0 K3 @@ -450,7 +451,10 @@ be_local_closure(load, /* name */ 0x7C140200, // 002A CALL R5 1 0x50140000, // 002B LDBOOL R5 0 0 0x90021405, // 002C SETMBR R0 K10 R5 - 0x80000000, // 002D RET 0 + 0x70020001, // 002D JMP #0030 + 0x8C14010B, // 002E GETMET R5 R0 K11 + 0x7C140200, // 002F CALL R5 1 + 0x80000000, // 0030 RET 0 }) ) ); @@ -460,7 +464,7 @@ be_local_closure(load, /* name */ /******************************************************************** ** Solidified function: find ********************************************************************/ -be_local_closure(find, /* name */ +be_local_closure(Persist_find, /* name */ be_nested_proto( 7, /* nstack */ 3, /* argc */ @@ -471,8 +475,8 @@ be_local_closure(find, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_string("_p", 1594591802, 2), - /* K1 */ be_nested_string("find", -1108310694, 4), + /* K0 */ be_nested_str_literal("_p"), + /* K1 */ be_nested_str_literal("find"), }), (be_nested_const_str("find", -1108310694, 4)), ((bstring*) &be_const_str_input), @@ -492,7 +496,7 @@ be_local_closure(find, /* name */ /******************************************************************** ** Solidified function: init ********************************************************************/ -be_local_closure(init, /* name */ +be_local_closure(Persist_init, /* name */ be_nested_proto( 6, /* nstack */ 2, /* argc */ @@ -503,12 +507,12 @@ be_local_closure(init, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_string("_filename", 1430813195, 9), - /* K1 */ be_nested_string("_persist.json", 2008425138, 13), - /* K2 */ be_nested_string("_p", 1594591802, 2), - /* K3 */ be_nested_string("copy", -446502332, 4), - /* K4 */ be_nested_string("load", -435725847, 4), - /* K5 */ be_nested_string("_dirty", 283846766, 6), + /* K0 */ be_nested_str_literal("_filename"), + /* K1 */ be_nested_str_literal("_persist.json"), + /* K2 */ be_nested_str_literal("_p"), + /* K3 */ be_nested_str_literal("copy"), + /* K4 */ be_nested_str_literal("load"), + /* K5 */ be_nested_str_literal("_dirty"), }), (be_nested_const_str("init", 380752755, 4)), ((bstring*) &be_const_str_input), @@ -542,7 +546,7 @@ be_local_closure(init, /* name */ /******************************************************************** ** Solidified function: json_fdump_list ********************************************************************/ -be_local_closure(json_fdump_list, /* name */ +be_local_closure(Persist_json_fdump_list, /* name */ be_nested_proto( 9, /* nstack */ 3, /* argc */ @@ -553,14 +557,14 @@ be_local_closure(json_fdump_list, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 8]) { /* constants */ - /* K0 */ be_nested_string("json", 916562499, 4), - /* K1 */ be_nested_string("write", -1104765092, 5), - /* K2 */ be_nested_string("[", -569630790, 1), + /* K0 */ be_nested_str_literal("json"), + /* K1 */ be_nested_str_literal("write"), + /* K2 */ be_nested_str_literal("["), /* K3 */ be_const_int(0), - /* K4 */ be_nested_string(",", 688690635, 1), - /* K5 */ be_nested_string("json_fdump_any", -946337911, 14), + /* K4 */ be_nested_str_literal(","), + /* K5 */ be_nested_str_literal("json_fdump_any"), /* K6 */ be_const_int(1), - /* K7 */ be_nested_string("]", -670296504, 1), + /* K7 */ be_nested_str_literal("]"), }), (be_nested_const_str("json_fdump_list", -391087443, 15)), ((bstring*) &be_const_str_input), @@ -599,7 +603,7 @@ be_local_closure(json_fdump_list, /* name */ /******************************************************************** ** Solidified function: has ********************************************************************/ -be_local_closure(has, /* name */ +be_local_closure(Persist_has, /* name */ be_nested_proto( 5, /* nstack */ 2, /* argc */ @@ -610,8 +614,8 @@ be_local_closure(has, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_string("_p", 1594591802, 2), - /* K1 */ be_nested_string("has", -306245661, 3), + /* K0 */ be_nested_str_literal("_p"), + /* K1 */ be_nested_str_literal("has"), }), (be_nested_const_str("has", -306245661, 3)), ((bstring*) &be_const_str_input), @@ -635,30 +639,30 @@ be_local_class(Persist, NULL, be_nested_map(16, ( (struct bmapnode*) &(const bmapnode[]) { - { be_nested_key("json_fdump_map", -203012643, 14, 5), be_const_closure(json_fdump_map_closure) }, - { be_nested_key("setmember", 1432909441, 9, -1), be_const_closure(setmember_closure) }, - { be_nested_key("zero", -1955600541, 4, 15), be_const_closure(zero_closure) }, - { be_nested_key("member", 719708611, 6, 12), be_const_closure(member_closure) }, - { be_nested_key("json_fdump", 1694216580, 10, -1), be_const_closure(json_fdump_closure) }, - { be_nested_key("remove", -611183107, 6, -1), be_const_closure(remove_closure) }, - { be_nested_key("json_fdump_any", -946337911, 14, -1), be_const_closure(json_fdump_any_closure) }, - { be_nested_key("_p", 1594591802, 2, -1), be_const_var(1) }, - { be_nested_key("save", -855671224, 4, -1), be_const_closure(save_closure) }, - { be_nested_key("load", -435725847, 4, 6), be_const_closure(load_closure) }, - { be_nested_key("find", -1108310694, 4, 7), be_const_closure(find_closure) }, + { be_nested_key("has", -306245661, 3, 6), be_const_closure(Persist_has_closure) }, + { be_nested_key("setmember", 1432909441, 9, -1), be_const_closure(Persist_setmember_closure) }, + { be_nested_key("remove", -611183107, 6, -1), be_const_closure(Persist_remove_closure) }, + { be_nested_key("zero", -1955600541, 4, 0), be_const_closure(Persist_zero_closure) }, + { be_nested_key("json_fdump", 1694216580, 10, -1), be_const_closure(Persist_json_fdump_closure) }, + { be_nested_key("json_fdump_list", -391087443, 15, 2), be_const_closure(Persist_json_fdump_list_closure) }, + { be_nested_key("init", 380752755, 4, 15), be_const_closure(Persist_init_closure) }, + { be_nested_key("find", -1108310694, 4, -1), be_const_closure(Persist_find_closure) }, + { be_nested_key("save", -855671224, 4, -1), be_const_closure(Persist_save_closure) }, + { be_nested_key("json_fdump_any", -946337911, 14, 12), be_const_closure(Persist_json_fdump_any_closure) }, + { be_nested_key("_p", 1594591802, 2, 7), be_const_var(1) }, { be_nested_key("_filename", 1430813195, 9, -1), be_const_var(0) }, - { be_nested_key("init", 380752755, 4, 2), be_const_closure(init_closure) }, - { be_nested_key("json_fdump_list", -391087443, 15, 0), be_const_closure(json_fdump_list_closure) }, + { be_nested_key("load", -435725847, 4, -1), be_const_closure(Persist_load_closure) }, + { be_nested_key("json_fdump_map", -203012643, 14, 5), be_const_closure(Persist_json_fdump_map_closure) }, { be_nested_key("_dirty", 283846766, 6, -1), be_const_var(2) }, - { be_nested_key("has", -306245661, 3, -1), be_const_closure(has_closure) }, + { be_nested_key("member", 719708611, 6, -1), be_const_closure(Persist_member_closure) }, })), - (be_nested_const_str("Persist", 1456346147, 7)) + be_str_literal("Persist") ); /******************************************************************** ** Solidified function: _anonymous_ ********************************************************************/ -be_local_closure(_anonymous_, /* name */ +be_local_closure(persist__anonymous_, /* name */ be_nested_proto( 3, /* nstack */ 1, /* argc */ @@ -692,7 +696,7 @@ be_local_module(persist, "persist", be_nested_map(1, ( (struct bmapnode*) &(const bmapnode[]) { - { be_nested_key("init", 380752755, 4, -1), be_const_closure(_anonymous__closure) }, + { be_nested_key("init", 380752755, 4, -1), be_const_closure(persist__anonymous__closure) }, })) ); BE_EXPORT_VARIABLE be_define_const_native_module(persist); diff --git a/lib/libesp32/Berry/default/embedded/persist.be b/lib/libesp32/Berry/default/embedded/persist.be index e0bb8025f..164a1dd7b 100644 --- a/lib/libesp32/Berry/default/embedded/persist.be +++ b/lib/libesp32/Berry/default/embedded/persist.be @@ -81,6 +81,8 @@ persist_module.init = def (m) print("BRY: failed to load _persist.json") end self._dirty = false + else + self.save() end # print("Loading") diff --git a/tasmota/xdrv_52_7_berry_embedded.ino b/tasmota/xdrv_52_7_berry_embedded.ino index a51409406..cbf933d07 100644 --- a/tasmota/xdrv_52_7_berry_embedded.ino +++ b/tasmota/xdrv_52_7_berry_embedded.ino @@ -31,8 +31,6 @@ const char berry_prog[] = // enable python syntax compatibility mode "import python_compat " #endif - // persistance module - "import persist " #ifdef USE_ENERGY_SENSOR "import energy " From 0fad84fe0656ce8e93409c4f429839879091e44b Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sun, 28 Nov 2021 19:41:26 +0100 Subject: [PATCH 139/185] Berry fix ranges with negative indices --- lib/libesp32/Berry/src/be_listlib.c | 6 ++++++ lib/libesp32/Berry/tests/list.be | 11 +++++++++++ 2 files changed, 17 insertions(+) diff --git a/lib/libesp32/Berry/src/be_listlib.c b/lib/libesp32/Berry/src/be_listlib.c index b584aef90..a98b679df 100644 --- a/lib/libesp32/Berry/src/be_listlib.c +++ b/lib/libesp32/Berry/src/be_listlib.c @@ -134,9 +134,15 @@ static int item_range(bvm *vm) /* get index range */ be_getmember(vm, 2, "__lower__"); lower = be_toint(vm, -1); + if (lower < 0) { + lower = size + lower; + } be_pop(vm, 1); be_getmember(vm, 2, "__upper__"); upper = be_toint(vm, -1); + if (upper < 0) { + upper = size + upper; + } be_pop(vm, 1); /* protection scope */ upper = upper < size ? upper : size - 1; diff --git a/lib/libesp32/Berry/tests/list.be b/lib/libesp32/Berry/tests/list.be index d0b9099ba..a2da2ca47 100644 --- a/lib/libesp32/Berry/tests/list.be +++ b/lib/libesp32/Berry/tests/list.be @@ -127,3 +127,14 @@ assert([1,2,3].concat('-') == "1-2-3") assert([1,"2",3].concat('-') == "1-2-3") assert(["",2,3].concat('-') == "-2-3") + +#- negative indices -# +assert([1,2,3,4][0] == 1) +assert([1,2,3,4][-1] == 4) +assert([1,2,3,4][-2] == 3) + +assert([1,2,3,4][1..10] == [2,3,4]) +assert([1,2,3,4][1..-1] == [2,3,4]) +assert([1,2,3,4][1..-2] == [2,3]) +assert([1,2,3,4][3..2] == []) +assert([1,2,3,4][2..-3] == []) \ No newline at end of file From 079f50cc20ee5d34544180c3cd490598b92a8b25 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sun, 28 Nov 2021 20:13:03 +0100 Subject: [PATCH 140/185] Berry auto path when loading archive --- lib/libesp32/Berry/default/be_tasmotalib.c | 308 +++++++++++------- .../Berry/default/embedded/Tasmota.be | 26 ++ 2 files changed, 218 insertions(+), 116 deletions(-) diff --git a/lib/libesp32/Berry/default/be_tasmotalib.c b/lib/libesp32/Berry/default/be_tasmotalib.c index 76720b7b4..a5c0307b8 100644 --- a/lib/libesp32/Berry/default/be_tasmotalib.c +++ b/lib/libesp32/Berry/default/be_tasmotalib.c @@ -869,13 +869,80 @@ be_local_closure(time_str, /* name */ ********************************************************************/ be_local_closure(load, /* name */ be_nested_proto( - 19, /* nstack */ + 21, /* nstack */ 2, /* argc */ 0, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ + 1, /* has sup protos */ + ( &(const struct bproto*[ 2]) { + be_nested_proto( + 6, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_literal("sys"), + /* K1 */ be_nested_str_literal("path"), + /* K2 */ be_nested_str_literal("find"), + /* K3 */ be_nested_str_literal("push"), + }), + (be_nested_const_str("push_path", 1155254157, 9)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[13]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0x8C080301, // 0001 GETMET R2 R1 K1 + 0x7C080200, // 0002 CALL R2 1 + 0x8C0C0502, // 0003 GETMET R3 R2 K2 + 0x5C140000, // 0004 MOVE R5 R0 + 0x7C0C0400, // 0005 CALL R3 2 + 0x4C100000, // 0006 LDNIL R4 + 0x1C0C0604, // 0007 EQ R3 R3 R4 + 0x780E0002, // 0008 JMPF R3 #000C + 0x8C0C0503, // 0009 GETMET R3 R2 K3 + 0x5C140000, // 000A MOVE R5 R0 + 0x7C0C0400, // 000B CALL R3 2 + 0x80000000, // 000C RET 0 + }) + ), + be_nested_proto( + 7, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_literal("sys"), + /* K1 */ be_nested_str_literal("path"), + /* K2 */ be_nested_str_literal("find"), + /* K3 */ be_nested_str_literal("remove"), + }), + (be_nested_const_str("pop_path", -1891723298, 8)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[13]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0x8C080301, // 0001 GETMET R2 R1 K1 + 0x7C080200, // 0002 CALL R2 1 + 0x8C0C0502, // 0003 GETMET R3 R2 K2 + 0x5C140000, // 0004 MOVE R5 R0 + 0x7C0C0400, // 0005 CALL R3 2 + 0x4C100000, // 0006 LDNIL R4 + 0x20100604, // 0007 NE R4 R3 R4 + 0x78120002, // 0008 JMPF R4 #000C + 0x8C100503, // 0009 GETMET R4 R2 K3 + 0x5C180600, // 000A MOVE R6 R3 + 0x7C100400, // 000B CALL R4 2 + 0x80000000, // 000C RET 0 + }) + ), + }), 1, /* has constants */ ( &(const bvalue[21]) { /* constants */ /* K0 */ be_nested_str_literal("string"), @@ -902,119 +969,128 @@ be_local_closure(load, /* name */ }), (be_nested_const_str("load", -435725847, 4)), ((bstring*) &be_const_str_input), - ( &(const binstruction[112]) { /* code */ - 0xA40A0000, // 0000 IMPORT R2 K0 - 0xA40E0200, // 0001 IMPORT R3 K1 - 0x6010000C, // 0002 GETGBL R4 G12 - 0x5C140200, // 0003 MOVE R5 R1 - 0x7C100200, // 0004 CALL R4 1 - 0x1C100902, // 0005 EQ R4 R4 K2 - 0x78120001, // 0006 JMPF R4 #0009 - 0x50100000, // 0007 LDBOOL R4 0 0 - 0x80040800, // 0008 RET 1 R4 - 0x94100302, // 0009 GETIDX R4 R1 K2 - 0x20100903, // 000A NE R4 R4 K3 - 0x78120000, // 000B JMPF R4 #000D - 0x00060601, // 000C ADD R1 K3 R1 - 0x8C100504, // 000D GETMET R4 R2 K4 - 0x5C180200, // 000E MOVE R6 R1 - 0x581C0005, // 000F LDCONST R7 K5 - 0x7C100600, // 0010 CALL R4 3 - 0x94140902, // 0011 GETIDX R5 R4 K2 - 0x5419FFFE, // 0012 LDINT R6 -1 - 0x94180806, // 0013 GETIDX R6 R4 R6 - 0x601C000C, // 0014 GETGBL R7 G12 - 0x5C200800, // 0015 MOVE R8 R4 - 0x7C1C0200, // 0016 CALL R7 1 - 0x241C0F06, // 0017 GT R7 R7 K6 - 0x8C200507, // 0018 GETMET R8 R2 K7 - 0x5C280C00, // 0019 MOVE R10 R6 - 0x582C0008, // 001A LDCONST R11 K8 - 0x7C200600, // 001B CALL R8 3 - 0x14201102, // 001C LT R8 R8 K2 - 0x78220001, // 001D JMPF R8 #0020 - 0x00040309, // 001E ADD R1 R1 K9 - 0x00180D09, // 001F ADD R6 R6 K9 - 0x5421FFFC, // 0020 LDINT R8 -3 - 0x5425FFFE, // 0021 LDINT R9 -1 - 0x40201009, // 0022 CONNECT R8 R8 R9 - 0x94200C08, // 0023 GETIDX R8 R6 R8 - 0x1C201109, // 0024 EQ R8 R8 K9 - 0x5425FFFB, // 0025 LDINT R9 -4 - 0x5429FFFE, // 0026 LDINT R10 -1 - 0x4024120A, // 0027 CONNECT R9 R9 R10 - 0x94240C09, // 0028 GETIDX R9 R6 R9 - 0x1C24130A, // 0029 EQ R9 R9 K10 - 0x5C281000, // 002A MOVE R10 R8 - 0x742A0002, // 002B JMPT R10 #002F - 0x5C281200, // 002C MOVE R10 R9 - 0x742A0000, // 002D JMPT R10 #002F - 0xB006170C, // 002E RAISE 1 K11 K12 - 0x8C28070D, // 002F GETMET R10 R3 K13 - 0x5C300A00, // 0030 MOVE R12 R5 - 0x7C280400, // 0031 CALL R10 2 - 0x78260005, // 0032 JMPF R9 #0039 - 0x4C2C0000, // 0033 LDNIL R11 - 0x1C2C140B, // 0034 EQ R11 R10 R11 - 0x782E0001, // 0035 JMPF R11 #0038 - 0x502C0000, // 0036 LDBOOL R11 0 0 - 0x80041600, // 0037 RET 1 R11 - 0x70020013, // 0038 JMP #004D - 0x8C2C070D, // 0039 GETMET R11 R3 K13 - 0x0034030E, // 003A ADD R13 R1 K14 - 0x7C2C0400, // 003B CALL R11 2 - 0x4C300000, // 003C LDNIL R12 - 0x1C30140C, // 003D EQ R12 R10 R12 - 0x78320004, // 003E JMPF R12 #0044 - 0x4C300000, // 003F LDNIL R12 - 0x1C30160C, // 0040 EQ R12 R11 R12 - 0x78320001, // 0041 JMPF R12 #0044 - 0x50300000, // 0042 LDBOOL R12 0 0 - 0x80041800, // 0043 RET 1 R12 - 0x4C300000, // 0044 LDNIL R12 - 0x2030160C, // 0045 NE R12 R11 R12 - 0x78320005, // 0046 JMPF R12 #004D - 0x4C300000, // 0047 LDNIL R12 - 0x1C30140C, // 0048 EQ R12 R10 R12 - 0x74320001, // 0049 JMPT R12 #004C - 0x2830160A, // 004A GE R12 R11 R10 - 0x78320000, // 004B JMPF R12 #004D - 0x50240200, // 004C LDBOOL R9 1 0 - 0x781E0002, // 004D JMPF R7 #0051 - 0x002C0B05, // 004E ADD R11 R5 K5 - 0x90021E0B, // 004F SETMBR R0 K15 R11 - 0x70020000, // 0050 JMP #0052 - 0x90021F10, // 0051 SETMBR R0 K15 K16 - 0x602C000D, // 0052 GETGBL R11 G13 - 0x5C300200, // 0053 MOVE R12 R1 - 0x58340011, // 0054 LDCONST R13 K17 - 0x7C2C0400, // 0055 CALL R11 2 - 0x5C301200, // 0056 MOVE R12 R9 - 0x74320013, // 0057 JMPT R12 #006C - 0x5C300E00, // 0058 MOVE R12 R7 - 0x74320011, // 0059 JMPT R12 #006C - 0xA8020005, // 005A EXBLK 0 #0061 - 0x8C300112, // 005B GETMET R12 R0 K18 - 0x0038030E, // 005C ADD R14 R1 K14 - 0x5C3C1600, // 005D MOVE R15 R11 - 0x7C300600, // 005E CALL R12 3 - 0xA8040001, // 005F EXBLK 1 1 - 0x7002000A, // 0060 JMP #006C - 0xAC300001, // 0061 CATCH R12 0 1 - 0x70020007, // 0062 JMP #006B - 0x60340001, // 0063 GETGBL R13 G1 - 0x8C380513, // 0064 GETMET R14 R2 K19 - 0x58400014, // 0065 LDCONST R16 K20 - 0x0044030E, // 0066 ADD R17 R1 K14 - 0x5C481800, // 0067 MOVE R18 R12 - 0x7C380800, // 0068 CALL R14 4 - 0x7C340200, // 0069 CALL R13 1 - 0x70020000, // 006A JMP #006C - 0xB0080000, // 006B RAISE 2 R0 R0 - 0x5C301600, // 006C MOVE R12 R11 - 0x7C300000, // 006D CALL R12 0 - 0x50300200, // 006E LDBOOL R12 1 0 - 0x80041800, // 006F RET 1 R12 + ( &(const binstruction[121]) { /* code */ + 0x84080000, // 0000 CLOSURE R2 P0 + 0x840C0001, // 0001 CLOSURE R3 P1 + 0xA4120000, // 0002 IMPORT R4 K0 + 0xA4160200, // 0003 IMPORT R5 K1 + 0x6018000C, // 0004 GETGBL R6 G12 + 0x5C1C0200, // 0005 MOVE R7 R1 + 0x7C180200, // 0006 CALL R6 1 + 0x1C180D02, // 0007 EQ R6 R6 K2 + 0x781A0001, // 0008 JMPF R6 #000B + 0x50180000, // 0009 LDBOOL R6 0 0 + 0x80040C00, // 000A RET 1 R6 + 0x94180302, // 000B GETIDX R6 R1 K2 + 0x20180D03, // 000C NE R6 R6 K3 + 0x781A0000, // 000D JMPF R6 #000F + 0x00060601, // 000E ADD R1 K3 R1 + 0x8C180904, // 000F GETMET R6 R4 K4 + 0x5C200200, // 0010 MOVE R8 R1 + 0x58240005, // 0011 LDCONST R9 K5 + 0x7C180600, // 0012 CALL R6 3 + 0x941C0D02, // 0013 GETIDX R7 R6 K2 + 0x5421FFFE, // 0014 LDINT R8 -1 + 0x94200C08, // 0015 GETIDX R8 R6 R8 + 0x6024000C, // 0016 GETGBL R9 G12 + 0x5C280C00, // 0017 MOVE R10 R6 + 0x7C240200, // 0018 CALL R9 1 + 0x24241306, // 0019 GT R9 R9 K6 + 0x8C280907, // 001A GETMET R10 R4 K7 + 0x5C301000, // 001B MOVE R12 R8 + 0x58340008, // 001C LDCONST R13 K8 + 0x7C280600, // 001D CALL R10 3 + 0x14281502, // 001E LT R10 R10 K2 + 0x782A0001, // 001F JMPF R10 #0022 + 0x00040309, // 0020 ADD R1 R1 K9 + 0x00201109, // 0021 ADD R8 R8 K9 + 0x5429FFFC, // 0022 LDINT R10 -3 + 0x542DFFFE, // 0023 LDINT R11 -1 + 0x4028140B, // 0024 CONNECT R10 R10 R11 + 0x9428100A, // 0025 GETIDX R10 R8 R10 + 0x1C281509, // 0026 EQ R10 R10 K9 + 0x542DFFFB, // 0027 LDINT R11 -4 + 0x5431FFFE, // 0028 LDINT R12 -1 + 0x402C160C, // 0029 CONNECT R11 R11 R12 + 0x942C100B, // 002A GETIDX R11 R8 R11 + 0x1C2C170A, // 002B EQ R11 R11 K10 + 0x5C301400, // 002C MOVE R12 R10 + 0x74320002, // 002D JMPT R12 #0031 + 0x5C301600, // 002E MOVE R12 R11 + 0x74320000, // 002F JMPT R12 #0031 + 0xB006170C, // 0030 RAISE 1 K11 K12 + 0x8C300B0D, // 0031 GETMET R12 R5 K13 + 0x5C380E00, // 0032 MOVE R14 R7 + 0x7C300400, // 0033 CALL R12 2 + 0x782E0005, // 0034 JMPF R11 #003B + 0x4C340000, // 0035 LDNIL R13 + 0x1C34180D, // 0036 EQ R13 R12 R13 + 0x78360001, // 0037 JMPF R13 #003A + 0x50340000, // 0038 LDBOOL R13 0 0 + 0x80041A00, // 0039 RET 1 R13 + 0x70020013, // 003A JMP #004F + 0x8C340B0D, // 003B GETMET R13 R5 K13 + 0x003C030E, // 003C ADD R15 R1 K14 + 0x7C340400, // 003D CALL R13 2 + 0x4C380000, // 003E LDNIL R14 + 0x1C38180E, // 003F EQ R14 R12 R14 + 0x783A0004, // 0040 JMPF R14 #0046 + 0x4C380000, // 0041 LDNIL R14 + 0x1C381A0E, // 0042 EQ R14 R13 R14 + 0x783A0001, // 0043 JMPF R14 #0046 + 0x50380000, // 0044 LDBOOL R14 0 0 + 0x80041C00, // 0045 RET 1 R14 + 0x4C380000, // 0046 LDNIL R14 + 0x20381A0E, // 0047 NE R14 R13 R14 + 0x783A0005, // 0048 JMPF R14 #004F + 0x4C380000, // 0049 LDNIL R14 + 0x1C38180E, // 004A EQ R14 R12 R14 + 0x743A0001, // 004B JMPT R14 #004E + 0x28381A0C, // 004C GE R14 R13 R12 + 0x783A0000, // 004D JMPF R14 #004F + 0x502C0200, // 004E LDBOOL R11 1 0 + 0x78260005, // 004F JMPF R9 #0056 + 0x00340F05, // 0050 ADD R13 R7 K5 + 0x90021E0D, // 0051 SETMBR R0 K15 R13 + 0x5C340400, // 0052 MOVE R13 R2 + 0x8838010F, // 0053 GETMBR R14 R0 K15 + 0x7C340200, // 0054 CALL R13 1 + 0x70020000, // 0055 JMP #0057 + 0x90021F10, // 0056 SETMBR R0 K15 K16 + 0x6034000D, // 0057 GETGBL R13 G13 + 0x5C380200, // 0058 MOVE R14 R1 + 0x583C0011, // 0059 LDCONST R15 K17 + 0x7C340400, // 005A CALL R13 2 + 0x5C381600, // 005B MOVE R14 R11 + 0x743A0013, // 005C JMPT R14 #0071 + 0x5C381200, // 005D MOVE R14 R9 + 0x743A0011, // 005E JMPT R14 #0071 + 0xA8020005, // 005F EXBLK 0 #0066 + 0x8C380112, // 0060 GETMET R14 R0 K18 + 0x0040030E, // 0061 ADD R16 R1 K14 + 0x5C441A00, // 0062 MOVE R17 R13 + 0x7C380600, // 0063 CALL R14 3 + 0xA8040001, // 0064 EXBLK 1 1 + 0x7002000A, // 0065 JMP #0071 + 0xAC380001, // 0066 CATCH R14 0 1 + 0x70020007, // 0067 JMP #0070 + 0x603C0001, // 0068 GETGBL R15 G1 + 0x8C400913, // 0069 GETMET R16 R4 K19 + 0x58480014, // 006A LDCONST R18 K20 + 0x004C030E, // 006B ADD R19 R1 K14 + 0x5C501C00, // 006C MOVE R20 R14 + 0x7C400800, // 006D CALL R16 4 + 0x7C3C0200, // 006E CALL R15 1 + 0x70020000, // 006F JMP #0071 + 0xB0080000, // 0070 RAISE 2 R0 R0 + 0x5C381A00, // 0071 MOVE R14 R13 + 0x7C380000, // 0072 CALL R14 0 + 0x78260002, // 0073 JMPF R9 #0077 + 0x5C380600, // 0074 MOVE R14 R3 + 0x003C0F05, // 0075 ADD R15 R7 K5 + 0x7C380200, // 0076 CALL R14 1 + 0x50380200, // 0077 LDBOOL R14 1 0 + 0x80041C00, // 0078 RET 1 R14 }) ) ); diff --git a/lib/libesp32/Berry/default/embedded/Tasmota.be b/lib/libesp32/Berry/default/embedded/Tasmota.be index 814af338f..3305d57ff 100644 --- a/lib/libesp32/Berry/default/embedded/Tasmota.be +++ b/lib/libesp32/Berry/default/embedded/Tasmota.be @@ -330,6 +330,25 @@ class Tasmota end def load(f) + # embedded functions + # puth_path: adds the current archive to sys.path + def push_path(p) + import sys + var path = sys.path() + if path.find(p) == nil # append only if it's not already there + path.push(p) + end + end + # pop_path: removes the path + def pop_path(p) + import sys + var path = sys.path() + var idx = path.find(p) + if idx != nil + path.remove(idx) + end + end + import string import path @@ -382,6 +401,7 @@ class Tasmota # recall the working directory if f_archive self.wd = f_prefix + "#" + push_path(self.wd) else self.wd = "" end @@ -398,6 +418,12 @@ class Tasmota # call the compiled code c() # call successfuls + + # remove path prefix + if f_archive + pop_path(f_prefix + "#") + end + return true end From dff20c41adaa50488841830ee50de50ba6140002 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sun, 28 Nov 2021 22:48:36 +0100 Subject: [PATCH 141/185] WS2812 RMT work-around --- tasmota/xlgt_01_ws2812.ino | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tasmota/xlgt_01_ws2812.ino b/tasmota/xlgt_01_ws2812.ino index 3a9e396f3..763f3e89e 100644 --- a/tasmota/xlgt_01_ws2812.ino +++ b/tasmota/xlgt_01_ws2812.ino @@ -224,6 +224,9 @@ void Ws2812StripShow(void) } } strip->Show(); +#ifdef ESP32 // workaround for SPI conflict + rmt_wait_tx_done((rmt_channel_t) USE_WS2812_RMT, 50/portTICK_PERIOD_MS); +#endif } int mod(int a, int b) @@ -497,6 +500,9 @@ void Ws2812Clear(void) strip->ClearTo(0); strip->Show(); Ws2812.show_next = 1; +#ifdef ESP32 // workaround for SPI conflict + rmt_wait_tx_done((rmt_channel_t) USE_WS2812_RMT, 50/portTICK_PERIOD_MS); +#endif } void Ws2812SetColor(uint32_t led, uint8_t red, uint8_t green, uint8_t blue, uint8_t white) @@ -523,6 +529,9 @@ void Ws2812SetColor(uint32_t led, uint8_t red, uint8_t green, uint8_t blue, uint if (!Ws2812.suspend_update) { strip->Show(); Ws2812.show_next = 1; +#ifdef ESP32 // workaround for SPI conflict + rmt_wait_tx_done((rmt_channel_t) USE_WS2812_RMT, 50/portTICK_PERIOD_MS); +#endif } } @@ -564,6 +573,9 @@ void Ws2812ForceUpdate (void) Ws2812.suspend_update = false; strip->Show(); Ws2812.show_next = 1; +#ifdef ESP32 // workaround for SPI conflict + rmt_wait_tx_done((rmt_channel_t) USE_WS2812_RMT, 50/portTICK_PERIOD_MS); +#endif } /********************************************************************************************/ From 80d7f2e2ef4513d1d0c14fabea753ad4a61d26a8 Mon Sep 17 00:00:00 2001 From: Tortue95 Date: Sun, 28 Nov 2021 23:26:20 +0100 Subject: [PATCH 142/185] Tuya: DimmerRange issue **Related issue:** https://github.com/arendst/Tasmota/issues/11349#issuecomment-978348187 https://github.com/arendst/Tasmota/issues/11349#issuecomment-978348187 I did not dare to modify the DimmerRange for the CTLight, because I do not have one to test --- tasmota/xdrv_16_tuyamcu.ino | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tasmota/xdrv_16_tuyamcu.ino b/tasmota/xdrv_16_tuyamcu.ino index c00765f0e..43b703c82 100644 --- a/tasmota/xdrv_16_tuyamcu.ino +++ b/tasmota/xdrv_16_tuyamcu.ino @@ -663,7 +663,7 @@ void LightSerialDuty(uint16_t duty, char *hex_char, uint8_t TuyaIdx) if (duty > 0 && !Tuya.ignore_dim && TuyaSerial && dpid > 0) { if (TuyaIdx == 2 && CTLight) { duty = changeUIntScale(duty, Tuya.CTMin, Tuya.CTMax, Settings->dimmer_hw_max, 0); - } else { duty = changeUIntScale(duty, 0, 100, 0, Settings->dimmer_hw_max); } + } else { duty = changeUIntScale(duty, 0, 100, Settings->dimmer_hw_min, Settings->dimmer_hw_max); } if (duty < Settings->dimmer_hw_min) { duty = Settings->dimmer_hw_min; } // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself Tuya.ignore_dimmer_cmd_timeout = millis() + 250; // Ignore serial received dim commands for the next 250ms @@ -679,7 +679,7 @@ void LightSerialDuty(uint16_t duty, char *hex_char, uint8_t TuyaIdx) if (TuyaIdx == 2 && CTLight) { duty = changeUIntScale(duty, Tuya.CTMin, Tuya.CTMax, Settings->dimmer_hw_max, 0); } else { - duty = changeUIntScale(duty, 0, 100, 0, Settings->dimmer_hw_max); + duty = changeUIntScale(duty, 0, 100, Settings->dimmer_hw_min, Settings->dimmer_hw_max); } AddLog(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim skipped value %d for dpid %d"), duty, dpid); // due to 0 or already set } else { @@ -768,7 +768,7 @@ void TuyaProcessStatePacket(void) { if (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) { AddLog(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[dpidStart + 4]?"On":"Off",bitRead(TasmotaGlobal.power, fnId - TUYA_MCU_FUNC_REL1)?"On":"Off"); - if ((TasmotaGlobal.power || Settings->light_dimmer > 0) && (Tuya.buffer[dpidStart + 4] != bitRead(TasmotaGlobal.power, fnId - TUYA_MCU_FUNC_REL1))) { + if (Tuya.buffer[dpidStart + 4] != bitRead(TasmotaGlobal.power, fnId - TUYA_MCU_FUNC_REL1)) { if (!Tuya.buffer[dpidStart + 4]) { PowerOff = true; } ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[dpidStart + 4], SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction } @@ -832,7 +832,7 @@ void TuyaProcessStatePacket(void) { if (dimIndex == 1 && !Settings->flag3.pwm_multi_channels) { Tuya.Levels[1] = changeUIntScale(packetValue, 0, Settings->dimmer_hw_max, Tuya.CTMax, Tuya.CTMin); } else { - Tuya.Levels[dimIndex] = changeUIntScale(packetValue, 0, Settings->dimmer_hw_max, 0, 100); + Tuya.Levels[dimIndex] = changeUIntScale(packetValue, Settings->dimmer_hw_min, Settings->dimmer_hw_max, 0, 100); } AddLog(LOG_LEVEL_DEBUG, PSTR("TYA: RX value %d from dpId %d "), packetValue, Tuya.buffer[dpidStart]); From 2e16db474fae3f49edc948e5488bc6144c099428 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Mon, 29 Nov 2021 09:50:14 +0100 Subject: [PATCH 143/185] Revert "WS2812 RMT work-around" --- tasmota/xlgt_01_ws2812.ino | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/tasmota/xlgt_01_ws2812.ino b/tasmota/xlgt_01_ws2812.ino index 763f3e89e..3a9e396f3 100644 --- a/tasmota/xlgt_01_ws2812.ino +++ b/tasmota/xlgt_01_ws2812.ino @@ -224,9 +224,6 @@ void Ws2812StripShow(void) } } strip->Show(); -#ifdef ESP32 // workaround for SPI conflict - rmt_wait_tx_done((rmt_channel_t) USE_WS2812_RMT, 50/portTICK_PERIOD_MS); -#endif } int mod(int a, int b) @@ -500,9 +497,6 @@ void Ws2812Clear(void) strip->ClearTo(0); strip->Show(); Ws2812.show_next = 1; -#ifdef ESP32 // workaround for SPI conflict - rmt_wait_tx_done((rmt_channel_t) USE_WS2812_RMT, 50/portTICK_PERIOD_MS); -#endif } void Ws2812SetColor(uint32_t led, uint8_t red, uint8_t green, uint8_t blue, uint8_t white) @@ -529,9 +523,6 @@ void Ws2812SetColor(uint32_t led, uint8_t red, uint8_t green, uint8_t blue, uint if (!Ws2812.suspend_update) { strip->Show(); Ws2812.show_next = 1; -#ifdef ESP32 // workaround for SPI conflict - rmt_wait_tx_done((rmt_channel_t) USE_WS2812_RMT, 50/portTICK_PERIOD_MS); -#endif } } @@ -573,9 +564,6 @@ void Ws2812ForceUpdate (void) Ws2812.suspend_update = false; strip->Show(); Ws2812.show_next = 1; -#ifdef ESP32 // workaround for SPI conflict - rmt_wait_tx_done((rmt_channel_t) USE_WS2812_RMT, 50/portTICK_PERIOD_MS); -#endif } /********************************************************************************************/ From 84e9f2263de3c7b4c998ef84ae1b0fb28b258871 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Mon, 29 Nov 2021 09:57:10 +0100 Subject: [PATCH 144/185] Fix WS2812 crash --- lib/lib_basic/NeoPixelBus/src/internal/NeoEsp32RmtMethod.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/lib_basic/NeoPixelBus/src/internal/NeoEsp32RmtMethod.h b/lib/lib_basic/NeoPixelBus/src/internal/NeoEsp32RmtMethod.h index 6d98ccd04..2d1f184d8 100644 --- a/lib/lib_basic/NeoPixelBus/src/internal/NeoEsp32RmtMethod.h +++ b/lib/lib_basic/NeoPixelBus/src/internal/NeoEsp32RmtMethod.h @@ -554,7 +554,7 @@ public: config.clk_div = T_SPEED::RmtClockDivider; ESP_ERROR_CHECK(rmt_config(&config)); - ESP_ERROR_CHECK(rmt_driver_install(_channel.RmtChannelNumber, 0, ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_LEVEL1)); + ESP_ERROR_CHECK(rmt_driver_install(_channel.RmtChannelNumber, 0, 0)); ESP_ERROR_CHECK(rmt_translator_init(_channel.RmtChannelNumber, T_SPEED::Translate)); } From 990065df69bb4feabba0f76c439c7b95d59db2c9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 29 Nov 2021 11:29:38 +0100 Subject: [PATCH 145/185] Use tmp_copy repo for branch master --- .github/workflows/Tasmota_build_master.yml | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/.github/workflows/Tasmota_build_master.yml b/.github/workflows/Tasmota_build_master.yml index 148f18202..4639fde5e 100644 --- a/.github/workflows/Tasmota_build_master.yml +++ b/.github/workflows/Tasmota_build_master.yml @@ -1365,28 +1365,35 @@ jobs: [ ! -f ./mv_firmware/firmware/tasmota32c3*.* ] || mv ./mv_firmware/firmware/tasmota32c3*.* ./release-firmware/tasmota32/ [ ! -f ./mv_firmware/firmware/tasmota32* ] || mv ./mv_firmware/firmware/tasmota32* ./release-firmware/tasmota32/languages/ [ ! -f ./mv_firmware/firmware/* ] || mv ./mv_firmware/firmware/* ./release-firmware/tasmota/languages/ - - name: Display files + - name: Display files to transfer run: ls -R ./* - - name: Push Firmware files to https://github.com/arendst/Tasmota-firmware + - name: Push Firmware files to tmp_copy repo uses: Jason2866/copy_file_to_another_repo_action@main env: API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }} with: source_file: 'release-firmware' - destination_repo: 'arendst/Tasmota-firmware' + destination_repo: 'arendst/tmp_copy' + destination_branch: 'firmware' user_email: 'github-actions@github.com' user_name: 'github-actions' + + Start_final_copy: + needs: Upload + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 - name: Creat trigger.txt run: | echo ${GITHUB_SHA} &> trigger.txt echo "$( Date: Mon, 29 Nov 2021 19:27:09 +0100 Subject: [PATCH 146/185] add tuya_allow_dimmer_0 (SetOption131) --- tasmota/my_user_config.h | 1 + tasmota/settings.h | 2 +- tasmota/settings.ino | 1 + tasmota/xdrv_16_tuyamcu.ino | 3 ++- 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index bf887ff19..d9eb64830 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -337,6 +337,7 @@ #define RF_DATA_RADIX false // [SetOption28] RF receive data format (false = hexadecimal, true = decimal) #define IR_DATA_RADIX false // [SetOption29] IR receive data format (false = hexadecimal, true = decimal) #define TUYA_SETOPTION_20 false // [SetOption54] Apply SetOption20 settings to Tuya device +#define TUYA_ALLOW_DIMMER_0 false // [SetOption131] Allow save dimmer = 0 receved by MCU #define TUYA_TEMP_SET_RES 1 // [TuyaTempSetRes] Maximum number of decimals (0 - 3) showing sensor TemperatureSet #define IR_ADD_RAW_DATA false // [SetOption58] Add IR Raw data to JSON message #define BUZZER_ENABLE false // [SetOption67] Enable buzzer when available diff --git a/tasmota/settings.h b/tasmota/settings.h index c75842aac..b168422fc 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -160,7 +160,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t disable_referer_chk : 1; // bit 14 (v9.5.0.5) - SetOption128 - (Web) Allow access without referer check uint32_t energy_phase : 1; // bit 15 (v9.5.0.9) - SetOption129 - (Energy) Show phase information uint32_t show_heap_with_timestamp : 1; // bit 16 (v9.5.0.9) - SetOption130 - (Debug) Show heap with logging timestamp - uint32_t spare17 : 1; // bit 17 + uint32_t tuya_allow_dimmer_0 : 1; // bit 17 (v10.0.0.3) - SetOption131 - (Tuya) Allow save dimmer = 0 receved by MCU uint32_t spare18 : 1; // bit 18 uint32_t spare19 : 1; // bit 19 uint32_t spare20 : 1; // bit 20 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index ec09129f4..bab1870db 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -1182,6 +1182,7 @@ void SettingsDefaultSet2(void) { // Tuya flag3.tuya_apply_o20 |= TUYA_SETOPTION_20; + flag5.tuya_allow_dimmer_0 |= TUYA_ALLOW_DIMMER_0; flag3.tuya_serial_mqtt_publish |= MQTT_TUYA_RECEIVED; mbflag2.temperature_set_res |= TUYA_TEMP_SET_RES; diff --git a/tasmota/xdrv_16_tuyamcu.ino b/tasmota/xdrv_16_tuyamcu.ino index 43b703c82..f44ea864f 100644 --- a/tasmota/xdrv_16_tuyamcu.ino +++ b/tasmota/xdrv_16_tuyamcu.ino @@ -842,7 +842,8 @@ void TuyaProcessStatePacket(void) { (fnId == TUYA_MCU_FUNC_CT) || (fnId == TUYA_MCU_FUNC_WHITE)) { if (Tuya.ignore_dimmer_cmd_timeout < millis()) { - if ((TasmotaGlobal.power || Settings->flag3.tuya_apply_o20) && ((Tuya.Levels[dimIndex] > 0) && (Tuya.Levels[dimIndex] != Tuya.Snapshot[dimIndex]))) { // SetOption54 - Apply SetOption20 settings to Tuya device + //if ((TasmotaGlobal.power || Settings->flag3.tuya_apply_o20) && ((Tuya.Levels[dimIndex] > 0) && (Tuya.Levels[dimIndex] != Tuya.Snapshot[dimIndex]))) { // SetOption54 - Apply SetOption20 settings to Tuya device + if ((TasmotaGlobal.power || Settings->flag3.tuya_apply_o20) && ((Tuya.Levels[dimIndex] > 0 || Settings->flag5.tuya_allow_dimmer_0) && (Tuya.Levels[dimIndex] != Tuya.Snapshot[dimIndex]))) { // SetOption54 - Apply SetOption20 settings to Tuya device Tuya.ignore_dim = true; TasmotaGlobal.skip_light_fade = true; From 0d4b12e5acbbebbeda2596b0d1d76e37a0c625d6 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Mon, 29 Nov 2021 21:30:06 +0100 Subject: [PATCH 147/185] Berry fix bool() --- lib/libesp32/Berry/generate/be_const_strtab.h | 1 + .../Berry/generate/be_const_strtab_def.h | 5 +- .../Berry/generate/be_fixed_m_builtin.h | 48 ++++++++++--------- 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/lib/libesp32/Berry/generate/be_const_strtab.h b/lib/libesp32/Berry/generate/be_const_strtab.h index cee6bc29d..daeb099fd 100644 --- a/lib/libesp32/Berry/generate/be_const_strtab.h +++ b/lib/libesp32/Berry/generate/be_const_strtab.h @@ -246,6 +246,7 @@ extern const bcstring be_const_str_event; extern const bcstring be_const_str_resp_cmnd_done; extern const bcstring be_const_str_AudioOutputI2S; extern const bcstring be_const_str_has_arg; +extern const bcstring be_const_str_bool; extern const bcstring be_const_str_floor; extern const bcstring be_const_str_read; extern const bcstring be_const_str_remove; diff --git a/lib/libesp32/Berry/generate/be_const_strtab_def.h b/lib/libesp32/Berry/generate/be_const_strtab_def.h index 16488ae94..5b49d263b 100644 --- a/lib/libesp32/Berry/generate/be_const_strtab_def.h +++ b/lib/libesp32/Berry/generate/be_const_strtab_def.h @@ -246,6 +246,7 @@ be_define_const_str(event, "event", 4264611999u, 0, 5, &be_const_str_resp_cmnd_d be_define_const_str(resp_cmnd_done, "resp_cmnd_done", 2601874875u, 0, 14, NULL); be_define_const_str(AudioOutputI2S, "AudioOutputI2S", 638031784u, 0, 14, &be_const_str_has_arg); be_define_const_str(has_arg, "has_arg", 424878688u, 0, 7, NULL); +be_define_const_str(bool, "bool", 3365180733u, 0, 4, &be_const_str_floor); be_define_const_str(floor, "floor", 3102149661u, 0, 5, &be_const_str_read); be_define_const_str(read, "read", 3470762949u, 0, 4, &be_const_str_remove); be_define_const_str(remove, "remove", 3683784189u, 0, 6, NULL); @@ -467,7 +468,7 @@ static const bstring* const m_string_table[] = { (const bstring *)&be_const_str_AudioGenerator, (const bstring *)&be_const_str_event, (const bstring *)&be_const_str_AudioOutputI2S, - (const bstring *)&be_const_str_floor, + (const bstring *)&be_const_str_bool, (const bstring *)&be_const_str_calldepth, (const bstring *)&be_const_str_gamma10, (const bstring *)&be_const_str__buffer, @@ -518,6 +519,6 @@ static const bstring* const m_string_table[] = { static const struct bconststrtab m_const_string_table = { .size = 164, - .count = 328, + .count = 329, .table = m_string_table }; diff --git a/lib/libesp32/Berry/generate/be_fixed_m_builtin.h b/lib/libesp32/Berry/generate/be_fixed_m_builtin.h index 57e049fc3..1a803b21b 100644 --- a/lib/libesp32/Berry/generate/be_fixed_m_builtin.h +++ b/lib/libesp32/Berry/generate/be_fixed_m_builtin.h @@ -1,34 +1,35 @@ #include "be_constobj.h" static be_define_const_map_slots(m_builtin_map) { - { be_const_key(number, 16), be_const_int(7) }, - { be_const_key(map, -1), be_const_int(19) }, - { be_const_key(classname, 22), be_const_int(5) }, - { be_const_key(bytes, 2), be_const_int(21) }, - { be_const_key(int, 12), be_const_int(9) }, - { be_const_key(module, -1), be_const_int(11) }, - { be_const_key(print, 20), be_const_int(1) }, - { be_const_key(issubclass, -1), be_const_int(14) }, - { be_const_key(assert, -1), be_const_int(0) }, - { be_const_key(list, -1), be_const_int(18) }, - { be_const_key(__iterator__, -1), be_const_int(16) }, - { be_const_key(real, -1), be_const_int(10) }, - { be_const_key(super, 21), be_const_int(3) }, - { be_const_key(isinstance, 8), be_const_int(15) }, - { be_const_key(classof, 4), be_const_int(6) }, - { be_const_key(input, -1), be_const_int(2) }, - { be_const_key(call, 19), be_const_int(22) }, - { be_const_key(compile, -1), be_const_int(13) }, - { be_const_key(open, -1), be_const_int(17) }, - { be_const_key(size, -1), be_const_int(12) }, + { be_const_key(number, 23), be_const_int(7) }, + { be_const_key(call, -1), be_const_int(22) }, { be_const_key(range, -1), be_const_int(20) }, + { be_const_key(input, -1), be_const_int(2) }, + { be_const_key(bytes, 11), be_const_int(21) }, + { be_const_key(issubclass, -1), be_const_int(14) }, + { be_const_key(compile, -1), be_const_int(13) }, + { be_const_key(open, 22), be_const_int(17) }, + { be_const_key(module, 17), be_const_int(11) }, + { be_const_key(list, 7), be_const_int(18) }, + { be_const_key(isinstance, -1), be_const_int(15) }, + { be_const_key(classname, 20), be_const_int(5) }, + { be_const_key(size, -1), be_const_int(12) }, + { be_const_key(real, -1), be_const_int(10) }, + { be_const_key(int, -1), be_const_int(9) }, + { be_const_key(__iterator__, 5), be_const_int(16) }, { be_const_key(str, -1), be_const_int(8) }, - { be_const_key(type, -1), be_const_int(4) }, + { be_const_key(bool, -1), be_const_int(23) }, + { be_const_key(classof, -1), be_const_int(6) }, + { be_const_key(assert, -1), be_const_int(0) }, + { be_const_key(super, -1), be_const_int(3) }, + { be_const_key(type, 8), be_const_int(4) }, + { be_const_key(map, -1), be_const_int(19) }, + { be_const_key(print, -1), be_const_int(1) }, }; static be_define_const_map( m_builtin_map, - 23 + 24 ); static const bvalue __vlist_array[] = { @@ -55,10 +56,11 @@ static const bvalue __vlist_array[] = { be_const_class(be_class_range), be_const_class(be_class_bytes), be_const_func(l_call), + be_const_func(l_bool), }; static be_define_const_vector( m_builtin_vector, __vlist_array, - 23 + 24 ); From 7bbd6bddfe45cd05358aa79649e71cb304385a01 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Mon, 29 Nov 2021 21:32:39 +0100 Subject: [PATCH 148/185] Berry fix stack corruption in solidify.dump --- lib/libesp32/Berry/src/be_solidifylib.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/libesp32/Berry/src/be_solidifylib.c b/lib/libesp32/Berry/src/be_solidifylib.c index 402db4547..d8291b365 100644 --- a/lib/libesp32/Berry/src/be_solidifylib.c +++ b/lib/libesp32/Berry/src/be_solidifylib.c @@ -125,9 +125,7 @@ static void m_solidify_bvalue(bvm *vm, bvalue * value, const char *classname, co be_pushstring(vm, str(var_tostr(value))); be_toescape(vm, -1, 'u'); logfmt("be_nested_str_literal(%s)", be_tostring(vm, -1)); - // logfmt("be_nested_string(%s", be_tostring(vm, -1)); - // be_pop(vm, 1); - // logfmt(", %i, %zu)", be_strhash(var_tostr(value)), len >= 255 ? 255 : len); + be_pop(vm, 1); } break; case BE_CLOSURE: From dbe0cdeaa350086f6570d469cf205107bde4336b Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Mon, 29 Nov 2021 21:35:20 +0100 Subject: [PATCH 149/185] Final fix for ESP32 WS2812 --- .../NeoPixelBus/src/internal/NeoEsp32RmtMethod.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/lib_basic/NeoPixelBus/src/internal/NeoEsp32RmtMethod.h b/lib/lib_basic/NeoPixelBus/src/internal/NeoEsp32RmtMethod.h index 2d1f184d8..2ed7e4a0e 100644 --- a/lib/lib_basic/NeoPixelBus/src/internal/NeoEsp32RmtMethod.h +++ b/lib/lib_basic/NeoPixelBus/src/internal/NeoEsp32RmtMethod.h @@ -50,6 +50,12 @@ extern "C" #include } +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 3, 0) +#define NEOPIXELBUS_RMT_INT_FLAGS (ESP_INTR_FLAG_LOWMED) +#else +#define NEOPIXELBUS_RMT_INT_FLAGS (ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_LEVEL1) +#endif + class NeoEsp32RmtSpeed { public: @@ -554,7 +560,7 @@ public: config.clk_div = T_SPEED::RmtClockDivider; ESP_ERROR_CHECK(rmt_config(&config)); - ESP_ERROR_CHECK(rmt_driver_install(_channel.RmtChannelNumber, 0, 0)); + ESP_ERROR_CHECK(rmt_driver_install(_channel.RmtChannelNumber, 0, NEOPIXELBUS_RMT_INT_FLAGS)); ESP_ERROR_CHECK(rmt_translator_init(_channel.RmtChannelNumber, T_SPEED::Translate)); } From 82aae68ccea89be7bb729286fd45c06abcce21e4 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Mon, 29 Nov 2021 21:44:44 +0100 Subject: [PATCH 150/185] Berry avoid TAP message in console --- lib/libesp32/Berry/default/be_tapp_lib.c | 86 +++++++++++---------- lib/libesp32/Berry/default/embedded/tapp.be | 2 +- 2 files changed, 46 insertions(+), 42 deletions(-) diff --git a/lib/libesp32/Berry/default/be_tapp_lib.c b/lib/libesp32/Berry/default/be_tapp_lib.c index 7a8cbe693..47ef170f7 100644 --- a/lib/libesp32/Berry/default/be_tapp_lib.c +++ b/lib/libesp32/Berry/default/be_tapp_lib.c @@ -9,7 +9,7 @@ /******************************************************************** ** Solidified function: init ********************************************************************/ -be_local_closure(init, /* name */ +be_local_closure(Tapp_init, /* name */ be_nested_proto( 4, /* nstack */ 1, /* argc */ @@ -20,8 +20,8 @@ be_local_closure(init, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_string("tasmota", 424643812, 7), - /* K1 */ be_nested_string("add_driver", 1654458371, 10), + /* K0 */ be_nested_str_literal("tasmota"), + /* K1 */ be_nested_str_literal("add_driver"), }), (be_nested_const_str("init", 380752755, 4)), ((bstring*) &be_const_str_input), @@ -40,9 +40,9 @@ be_local_closure(init, /* name */ /******************************************************************** ** Solidified function: autoexec ********************************************************************/ -be_local_closure(autoexec, /* name */ +be_local_closure(Tapp_autoexec, /* name */ be_nested_proto( - 11, /* nstack */ + 12, /* nstack */ 1, /* argc */ 0, /* varg */ 0, /* has upvals */ @@ -50,24 +50,26 @@ be_local_closure(autoexec, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[13]) { /* constants */ - /* K0 */ be_nested_string("path", -2071507658, 4), - /* K1 */ be_nested_string("string", 398550328, 6), - /* K2 */ be_nested_string("listdir", 2005220720, 7), - /* K3 */ be_nested_string("/", 705468254, 1), - /* K4 */ be_nested_string("find", -1108310694, 4), - /* K5 */ be_nested_string(".tapp", 1363391594, 5), + ( &(const bvalue[15]) { /* constants */ + /* K0 */ be_nested_str_literal("path"), + /* K1 */ be_nested_str_literal("string"), + /* K2 */ be_nested_str_literal("listdir"), + /* K3 */ be_nested_str_literal("/"), + /* K4 */ be_nested_str_literal("find"), + /* K5 */ be_nested_str_literal(".tapp"), /* K6 */ be_const_int(0), - /* K7 */ be_nested_string("format", -1180859054, 6), - /* K8 */ be_nested_string("TAP: found Tasmota App '%s'", -1651814898, 27), - /* K9 */ be_nested_string("tasmota", 424643812, 7), - /* K10 */ be_nested_string("load", -435725847, 4), - /* K11 */ be_nested_string("#autoexec.be", 1181757091, 12), - /* K12 */ be_nested_string("stop_iteration", -121173395, 14), + /* K7 */ be_nested_str_literal("tasmota"), + /* K8 */ be_nested_str_literal("log"), + /* K9 */ be_nested_str_literal("format"), + /* K10 */ be_nested_str_literal("TAP: found Tasmota App '%s'"), + /* K11 */ be_const_int(2), + /* K12 */ be_nested_str_literal("load"), + /* K13 */ be_nested_str_literal("#autoexec.be"), + /* K14 */ be_nested_str_literal("stop_iteration"), }), (be_nested_const_str("autoexec", -618105405, 8)), ((bstring*) &be_const_str_input), - ( &(const binstruction[32]) { /* code */ + ( &(const binstruction[34]) { /* code */ 0xA4060000, // 0000 IMPORT R1 K0 0xA40A0200, // 0001 IMPORT R2 K1 0x8C0C0302, // 0002 GETMET R3 R1 K2 @@ -76,7 +78,7 @@ be_local_closure(autoexec, /* name */ 0x60100010, // 0005 GETGBL R4 G16 0x5C140600, // 0006 MOVE R5 R3 0x7C100200, // 0007 CALL R4 1 - 0xA8020012, // 0008 EXBLK 0 #001C + 0xA8020014, // 0008 EXBLK 0 #001E 0x5C140800, // 0009 MOVE R5 R4 0x7C140000, // 000A CALL R5 0 0x8C180504, // 000B GETMET R6 R2 K4 @@ -84,22 +86,24 @@ be_local_closure(autoexec, /* name */ 0x58240005, // 000D LDCONST R9 K5 0x7C180600, // 000E CALL R6 3 0x24180D06, // 000F GT R6 R6 K6 - 0x781A0009, // 0010 JMPF R6 #001B - 0x60180001, // 0011 GETGBL R6 G1 - 0x8C1C0507, // 0012 GETMET R7 R2 K7 - 0x58240008, // 0013 LDCONST R9 K8 - 0x5C280A00, // 0014 MOVE R10 R5 - 0x7C1C0600, // 0015 CALL R7 3 - 0x7C180200, // 0016 CALL R6 1 - 0xB81A1200, // 0017 GETNGBL R6 K9 - 0x8C180D0A, // 0018 GETMET R6 R6 K10 - 0x00200B0B, // 0019 ADD R8 R5 K11 - 0x7C180400, // 001A CALL R6 2 - 0x7001FFEC, // 001B JMP #0009 - 0x5810000C, // 001C LDCONST R4 K12 - 0xAC100200, // 001D CATCH R4 1 0 - 0xB0080000, // 001E RAISE 2 R0 R0 - 0x80000000, // 001F RET 0 + 0x781A000B, // 0010 JMPF R6 #001D + 0xB81A0E00, // 0011 GETNGBL R6 K7 + 0x8C180D08, // 0012 GETMET R6 R6 K8 + 0x8C200509, // 0013 GETMET R8 R2 K9 + 0x5828000A, // 0014 LDCONST R10 K10 + 0x5C2C0A00, // 0015 MOVE R11 R5 + 0x7C200600, // 0016 CALL R8 3 + 0x5824000B, // 0017 LDCONST R9 K11 + 0x7C180600, // 0018 CALL R6 3 + 0xB81A0E00, // 0019 GETNGBL R6 K7 + 0x8C180D0C, // 001A GETMET R6 R6 K12 + 0x00200B0D, // 001B ADD R8 R5 K13 + 0x7C180400, // 001C CALL R6 2 + 0x7001FFEA, // 001D JMP #0009 + 0x5810000E, // 001E LDCONST R4 K14 + 0xAC100200, // 001F CATCH R4 1 0 + 0xB0080000, // 0020 RAISE 2 R0 R0 + 0x80000000, // 0021 RET 0 }) ) ); @@ -114,16 +118,16 @@ be_local_class(Tapp, NULL, be_nested_map(2, ( (struct bmapnode*) &(const bmapnode[]) { - { be_nested_key("init", 380752755, 4, -1), be_const_closure(init_closure) }, - { be_nested_key("autoexec", -618105405, 8, 0), be_const_closure(autoexec_closure) }, + { be_nested_key("autoexec", -618105405, 8, -1), be_const_closure(Tapp_autoexec_closure) }, + { be_nested_key("init", 380752755, 4, 0), be_const_closure(Tapp_init_closure) }, })), - (be_nested_const_str("Tapp", 2012315062, 4)) + be_str_literal("Tapp") ); /******************************************************************** ** Solidified function: _anonymous_ ********************************************************************/ -be_local_closure(_anonymous_, /* name */ +be_local_closure(tapp__anonymous_, /* name */ be_nested_proto( 3, /* nstack */ 1, /* argc */ @@ -157,7 +161,7 @@ be_local_module(tapp, "tapp", be_nested_map(1, ( (struct bmapnode*) &(const bmapnode[]) { - { be_nested_key("init", 380752755, 4, -1), be_const_closure(_anonymous__closure) }, + { be_nested_key("init", 380752755, 4, -1), be_const_closure(tapp__anonymous__closure) }, })) ); BE_EXPORT_VARIABLE be_define_const_native_module(tapp); diff --git a/lib/libesp32/Berry/default/embedded/tapp.be b/lib/libesp32/Berry/default/embedded/tapp.be index 3c3528e3a..30aa1f740 100644 --- a/lib/libesp32/Berry/default/embedded/tapp.be +++ b/lib/libesp32/Berry/default/embedded/tapp.be @@ -19,7 +19,7 @@ tapp_module.init = def (m) for d: dir if string.find(d, ".tapp") > 0 - print(string.format("TAP: found Tasmota App '%s'", d)) + tasmota.log(string.format("TAP: found Tasmota App '%s'", d), 2) tasmota.load(d + "#autoexec.be") end end From 992b11378f43974fef52981daf7f8fcebeb8b114 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Mon, 29 Nov 2021 21:51:46 +0100 Subject: [PATCH 151/185] Berry allocate logs in PSRAM --- tasmota/xdrv_52_0_berry_struct.ino | 38 +++++++++++++++++++++++------- tasmota/xdrv_52_9_berry.ino | 2 +- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/tasmota/xdrv_52_0_berry_struct.ino b/tasmota/xdrv_52_0_berry_struct.ino index 61ff080c5..70e443cb3 100644 --- a/tasmota/xdrv_52_0_berry_struct.ino +++ b/tasmota/xdrv_52_0_berry_struct.ino @@ -27,28 +27,48 @@ #define BERRY_CONSOLE_CMD_DELIMITER "\x01" -typedef LList_elt log_elt; // store the string after the header to avoid double allocation if we had used char* +class Log_line { +public: + Log_line() : log_line(nullptr) {} + ~Log_line() { + if (log_line != nullptr) { + berry_free(log_line); + } + } + char * getBuffer() { return log_line; } + char * allocate(size_t size) { + if (log_line != nullptr) { + berry_free(log_line); + } + log_line = (char*) berry_malloc(size); + return log_line; + } + + char * log_line; +}; + +// typedef LList_elt log_elt; // store the string after the header to avoid double allocation if we had used char* + class BerryLog { public: - // typedef LList_elt log_elt; // store the string after the header to avoid double allocation if we had used char* - inline static size_t size(size_t chars) { return sizeof(log_elt) + chars; } inline bool isEmpty(void) const { return log.isEmpty(); } - log_elt * addString(const char * s, const char * prefix = nullptr, const char * suffix = nullptr) { + LList_elt * addString(const char * s, const char * prefix = nullptr, const char * suffix = nullptr) { if (suffix == nullptr) { suffix = ""; } if (prefix == nullptr) { prefix = ""; } if (s == nullptr) { s = ""; } size_t s_len = strlen_P(s) + strlen_P(prefix) + strlen_P(suffix); if (0 == s_len) { return nullptr; } // do nothing - log_elt * elt = (log_elt*) ::operator new(sizeof(log_elt) + s_len + 1); // use low-level new to specify the bytes size - snprintf_P((char*) &elt->val(), s_len+1, PSTR("%s%s%s"), prefix, s, suffix); - log.addToLast(elt); - return elt; + LList_elt * log_elt = new LList_elt(); + log_elt->val().allocate(s_len + 1); + snprintf_P(log_elt->val().getBuffer(), s_len+1, PSTR("%s%s%s"), prefix, s, suffix); + log.addToLast(log_elt); + return log_elt; } void reset(void) { log.reset(); } - LList log; + LList log; }; class BerrySupport { diff --git a/tasmota/xdrv_52_9_berry.ino b/tasmota/xdrv_52_9_berry.ino index e938c5bb4..b59fa2f80 100644 --- a/tasmota/xdrv_52_9_berry.ino +++ b/tasmota/xdrv_52_9_berry.ino @@ -695,7 +695,7 @@ void HandleBerryConsoleRefresh(void) WSContentFlush(); for (auto & l: berry.log.log) { - _WSContentSend((char*) l); + _WSContentSend(l.getBuffer()); } berry.log.reset(); From 8632f971ece973a644ab8609c11603cf58ccfba4 Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Mon, 29 Nov 2021 14:53:24 -0600 Subject: [PATCH 152/185] Make sure PWM Dimmer night light stays updated --- tasmota/support_tasmota.ino | 3 +++ tasmota/tasmota.ino | 3 +++ tasmota/xdrv_35_pwm_dimmer.ino | 15 ++++----------- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 13671b18f..f3e4fe977 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -491,6 +491,9 @@ void SetLedLink(uint32_t state) #ifdef USE_BUZZER BuzzerSetStateToLed(state); #endif // USE_BUZZER +#ifdef USE_PWM_DIMMER + if (Settings->flag4.powered_off_led) TasmotaGlobal.restore_powered_off_led_counter = 3; +#endif // USE_PWM_DIMMER } void SetPulseTimer(uint32_t index, uint32_t time) diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 3e1ed63c4..872ad6ace 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -184,6 +184,9 @@ struct TasmotaGlobal_t { uint8_t last_source; // Last command source uint8_t shutters_present; // Number of actual define shutters uint8_t discovery_counter; // Delayed discovery counter +#ifdef USE_PWM_DIMMER + uint8_t restore_powered_off_led_counter; // Seconds before powered-off LED (LEDLink) is restored +#endif // USE_PWM_DIMMER #ifndef SUPPORT_IF_STATEMENT uint8_t backlog_index; // Command backlog index diff --git a/tasmota/xdrv_35_pwm_dimmer.ino b/tasmota/xdrv_35_pwm_dimmer.ino index 4b5101818..85d76c0af 100644 --- a/tasmota/xdrv_35_pwm_dimmer.ino +++ b/tasmota/xdrv_35_pwm_dimmer.ino @@ -63,7 +63,6 @@ struct remote_pwm_dimmer { uint32_t ignore_any_key_time = 0; uint32_t button_hold_time[3]; uint8_t led_timeout_seconds = 0; -uint8_t restore_powered_off_led_counter = 0; uint8_t power_button_index = 0; uint8_t down_button_index = 1; uint8_t buttons_pressed = 0; @@ -744,16 +743,10 @@ bool Xdrv35(uint8_t function) PWMDimmerSetBrightnessLeds(-2); } - // The powered-off LED is also the LedLink LED. If we lose the WiFi or MQTT server connection, - // the LED will be set to a blinking state and will be turned off when the connection is - // restored. If the state is blinking now, set a flag so we know that we need to restore it - // when it stops blinking. - if (TasmotaGlobal.global_state.data) - restore_powered_off_led_counter = 5; - else if (restore_powered_off_led_counter) { - PWMDimmerSetPoweredOffLed(); - restore_powered_off_led_counter--; - } + // The powered-off LED is also the LedLink LED. If the state of it gets changed, + // restore_powered_off_led_counter will get set to the number of seconds + // to wait before restoring it to the proper state. + if (TasmotaGlobal.restore_powered_off_led_counter && !--TasmotaGlobal.restore_powered_off_led_counter) PWMDimmerSetPoweredOffLed(); break; case FUNC_BUTTON_PRESSED: From 46b7347689f7c908b3307dda678c9b7e2a529086 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Mon, 29 Nov 2021 22:34:47 +0100 Subject: [PATCH 153/185] Berry limit size of log --- tasmota/xdrv_52_3_berry_tasmota.ino | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/tasmota/xdrv_52_3_berry_tasmota.ino b/tasmota/xdrv_52_3_berry_tasmota.ino index 667a8f7b2..83de43424 100644 --- a/tasmota/xdrv_52_3_berry_tasmota.ino +++ b/tasmota/xdrv_52_3_berry_tasmota.ino @@ -24,6 +24,7 @@ #include const uint32_t BERRY_MAX_LOGS = 16; // max number of print output recorded when outside of REPL, used to avoid infinite grow of logs +const uint32_t BERRY_MAX_REPL_LOGS = 1024; // max number of print output recorded when inside REPL /*********************************************************************************************\ * Return C callback from index @@ -575,16 +576,13 @@ extern "C" { void berry_log(const char * berry_buf); void berry_log(const char * berry_buf) { const char * pre_delimiter = nullptr; // do we need to prepend a delimiter if no REPL command - if (!berry.repl_active) { - // if no REPL in flight, we limit the number of logs - if (berry.log.log.length() == 0) { - pre_delimiter = BERRY_CONSOLE_CMD_DELIMITER; - } - if (berry.log.log.length() >= BERRY_MAX_LOGS) { - berry.log.log.remove(berry.log.log.head()); - } + size_t max_logs = berry.repl_active ? BERRY_MAX_REPL_LOGS : BERRY_MAX_LOGS; + if (berry.log.log.length() == 0) { + pre_delimiter = BERRY_CONSOLE_CMD_DELIMITER; + } + if (berry.log.log.length() >= BERRY_MAX_LOGS) { + berry.log.log.remove(berry.log.log.head()); } - // AddLog(LOG_LEVEL_INFO, PSTR("[Add to log] %s"), berry_buf); berry.log.addString(berry_buf, pre_delimiter, "\n"); AddLog(LOG_LEVEL_INFO, PSTR("%s"), berry_buf); } From 6cbe0198cc599f23def2a2afb62edcd3724fd2ed Mon Sep 17 00:00:00 2001 From: Tedrick DUFOUR Date: Mon, 29 Nov 2021 22:46:31 +0100 Subject: [PATCH 154/185] tuya_allow_dimmer_0: edit comment --- tasmota/xdrv_16_tuyamcu.ino | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tasmota/xdrv_16_tuyamcu.ino b/tasmota/xdrv_16_tuyamcu.ino index f44ea864f..250c28b21 100644 --- a/tasmota/xdrv_16_tuyamcu.ino +++ b/tasmota/xdrv_16_tuyamcu.ino @@ -842,8 +842,7 @@ void TuyaProcessStatePacket(void) { (fnId == TUYA_MCU_FUNC_CT) || (fnId == TUYA_MCU_FUNC_WHITE)) { if (Tuya.ignore_dimmer_cmd_timeout < millis()) { - //if ((TasmotaGlobal.power || Settings->flag3.tuya_apply_o20) && ((Tuya.Levels[dimIndex] > 0) && (Tuya.Levels[dimIndex] != Tuya.Snapshot[dimIndex]))) { // SetOption54 - Apply SetOption20 settings to Tuya device - if ((TasmotaGlobal.power || Settings->flag3.tuya_apply_o20) && ((Tuya.Levels[dimIndex] > 0 || Settings->flag5.tuya_allow_dimmer_0) && (Tuya.Levels[dimIndex] != Tuya.Snapshot[dimIndex]))) { // SetOption54 - Apply SetOption20 settings to Tuya device + if ((TasmotaGlobal.power || Settings->flag3.tuya_apply_o20) && ((Tuya.Levels[dimIndex] > 0 || Settings->flag5.tuya_allow_dimmer_0) && (Tuya.Levels[dimIndex] != Tuya.Snapshot[dimIndex]))) { // SetOption54 - Apply SetOption20 settings to Tuya device / SetOption131 Allow save dimmer = 0 receved by MCU Tuya.ignore_dim = true; TasmotaGlobal.skip_light_fade = true; From f77f77258f19426a9522bfa9dc75f4a861cf8dff Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Mon, 29 Nov 2021 23:11:25 +0100 Subject: [PATCH 155/185] Berry add `tasmota.global.devices_present` --- tasmota/xdrv_52_3_berry_tasmota_global.ino | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tasmota/xdrv_52_3_berry_tasmota_global.ino b/tasmota/xdrv_52_3_berry_tasmota_global.ino index affb2f19d..e5f3bad46 100644 --- a/tasmota/xdrv_52_3_berry_tasmota_global.ino +++ b/tasmota/xdrv_52_3_berry_tasmota_global.ino @@ -33,9 +33,10 @@ extern "C" { extern const be_ctypes_structure_t be_tasmota_global_struct = { sizeof(TasmotaGlobal), /* size in bytes */ - 1, /* number of elements */ + 2, /* number of elements */ nullptr, (const be_ctypes_structure_item_t[2]) { + { "devices_present", offsetof(TasmotaGlobal_t, devices_present), 0, 0, ctypes_u8, 0 }, { "sleep", offsetof(TasmotaGlobal_t, sleep), 0, 0, ctypes_u8, 0 }, }}; @@ -43,7 +44,7 @@ extern "C" { sizeof(TSettings), /* size in bytes */ 1, /* number of elements */ nullptr, - (const be_ctypes_structure_item_t[2]) { + (const be_ctypes_structure_item_t[1]) { { "sleep", offsetof(TSettings, sleep), 0, 0, ctypes_u8, 0 }, }}; From 38d834dda9abe0e2545898c664d6de3660503ad7 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Mon, 29 Nov 2021 23:21:21 +0100 Subject: [PATCH 156/185] Add `set_power` event --- tasmota/xdrv_52_9_berry.ino | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tasmota/xdrv_52_9_berry.ino b/tasmota/xdrv_52_9_berry.ino index b59fa2f80..15d47011d 100644 --- a/tasmota/xdrv_52_9_berry.ino +++ b/tasmota/xdrv_52_9_berry.ino @@ -811,8 +811,9 @@ bool Xdrv52(uint8_t function) case FUNC_EVERY_SECOND: callBerryEventDispatcher(PSTR("every_second"), nullptr, 0, nullptr); break; - // case FUNC_SET_POWER: - // break; + case FUNC_SET_POWER: + callBerryEventDispatcher(PSTR("set_power"), nullptr, XdrvMailbox.index, nullptr); + break; #ifdef USE_WEBSERVER case FUNC_WEB_ADD_CONSOLE_BUTTON: if (XdrvMailbox.index) { From a290a1b5de2910e0f8c4d8ba27fe9d3803ad08c1 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Mon, 29 Nov 2021 23:29:21 +0100 Subject: [PATCH 157/185] Rename to `set_power_handler` --- tasmota/xdrv_52_9_berry.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_52_9_berry.ino b/tasmota/xdrv_52_9_berry.ino index 15d47011d..bee52522e 100644 --- a/tasmota/xdrv_52_9_berry.ino +++ b/tasmota/xdrv_52_9_berry.ino @@ -812,7 +812,7 @@ bool Xdrv52(uint8_t function) callBerryEventDispatcher(PSTR("every_second"), nullptr, 0, nullptr); break; case FUNC_SET_POWER: - callBerryEventDispatcher(PSTR("set_power"), nullptr, XdrvMailbox.index, nullptr); + callBerryEventDispatcher(PSTR("set_power_handler"), nullptr, XdrvMailbox.index, nullptr); break; #ifdef USE_WEBSERVER case FUNC_WEB_ADD_CONSOLE_BUTTON: From 7e24f88f79855c4bc63bcd03b8a4fed3c9e72e07 Mon Sep 17 00:00:00 2001 From: Luc Boudreau Date: Sat, 27 Nov 2021 16:13:31 -0500 Subject: [PATCH 158/185] Adds some minimal sensor data to the thermostat driver to allow basic control by third party. --- tasmota/xdrv_39_thermostat.ino | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/tasmota/xdrv_39_thermostat.ino b/tasmota/xdrv_39_thermostat.ino index 60a8c7b10..ae8d2d92f 100644 --- a/tasmota/xdrv_39_thermostat.ino +++ b/tasmota/xdrv_39_thermostat.ino @@ -2022,8 +2022,17 @@ const char HTTP_THERMOSTAT_HL[] PROGMEM = "{s}
{m}
{e}"; #endif // USE_WEBSERVER -void ThermostatShow(uint8_t ctr_output) +void ThermostatShow(uint8_t ctr_output, bool json) { + if (json) { + float f_target_temp = Thermostat[ctr_output].temp_target_level / 10.0f; + ResponseAppend_P(PSTR(",\"Thermostat%i\":{"), ctr_output); + ResponseAppend_P(PSTR("%s\"%s\":%i"), "", D_CMND_THERMOSTATMODESET, Thermostat[ctr_output].status.thermostat_mode); + ResponseAppend_P(PSTR("%s\"%s\":%2_f"), ",", D_CMND_TEMPTARGETSET, &f_target_temp); + ResponseAppend_P(PSTR("%s\"%s\":%i"), ",", D_CMND_CTRDUTYCYCLEREAD, ThermostatGetDutyCycle(ctr_output)); + ResponseJsonEnd(); + return; + } #ifdef USE_WEBSERVER WSContentSend_P(HTTP_THERMOSTAT_HL); @@ -2110,11 +2119,16 @@ bool Xdrv39(uint8_t function) } } break; + case FUNC_JSON_APPEND: + for (ctr_output = 0; ctr_output < THERMOSTAT_CONTROLLER_OUTPUTS; ctr_output++) { + ThermostatShow(ctr_output, true); + } + break; #ifdef USE_WEBSERVER case FUNC_WEB_SENSOR: for (ctr_output = 0; ctr_output < THERMOSTAT_CONTROLLER_OUTPUTS; ctr_output++) { - ThermostatShow(ctr_output); + ThermostatShow(ctr_output, false); } break; #endif // USE_WEBSERVER From 6bd0140dd9e4b090ade5c43471095bd2b20cf92d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 30 Nov 2021 12:38:12 +0100 Subject: [PATCH 159/185] Fix function changeUIntScale edge cases --- tasmota/support_float.ino | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/tasmota/support_float.ino b/tasmota/support_float.ino index e2877e5a3..330daa480 100644 --- a/tasmota/support_float.ino +++ b/tasmota/support_float.ino @@ -407,14 +407,8 @@ uint16_t changeUIntScale(uint16_t inum, uint16_t ifrom_min, uint16_t ifrom_max, to_max = ito_min; } - uint32_t numerator = (num - from_min) * (to_max - to_min); - uint32_t result; - if (numerator >= 0x80000000L) { - // don't do rounding as it would create an overflow - result = numerator / (from_max - from_min) + to_min; - } else { - result = (((numerator * 2) / (from_max - from_min)) + 1) / 2 + to_min; - } + uint32_t numerator = (num - from_min) * (to_max - to_min + 1); + uint32_t result = numerator / (from_max - from_min) + to_min; return (uint32_t) (result > to_max ? to_max : (result < to_min ? to_min : result)); } From f2b98f7da3a02c646f416178ee791c8dd31a4cd9 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 30 Nov 2021 14:55:45 +0100 Subject: [PATCH 160/185] Add Xdrv function FUNC_BUTTON_MULTI_PRESSED --- tasmota/support_button.ino | 9 ++++++++- tasmota/tasmota.h | 2 +- tasmota/xdrv_04_light.ino | 3 +++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/tasmota/support_button.ino b/tasmota/support_button.ino index 3fbfff702..783ad475d 100644 --- a/tasmota/support_button.ino +++ b/tasmota/support_button.ino @@ -167,7 +167,7 @@ void ButtonHandler(void) { if (PinUsed(GPIO_KEY1, button_index)) { button_present = 1; #ifdef ESP32 -#ifndef CONFIG_IDF_TARGET_ESP32C3 +#ifndef CONFIG_IDF_TARGET_ESP32C3 if (bitRead(Button.touch_mask, button_index)) { // Touch uint32_t _value = touchRead(Pin(GPIO_KEY1, button_index)); button = NOT_PRESSED; @@ -313,6 +313,13 @@ void ButtonHandler(void) { } } } + + XdrvMailbox.index = button_index; + XdrvMailbox.payload = Button.press_counter[button_index]; + if (XdrvCall(FUNC_BUTTON_MULTI_PRESSED)) { + // Serviced + } else + #ifdef ROTARY_V1 if (!RotaryButtonPressed(button_index)) { #endif diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index f6a2b113d..77cbd00ce 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -341,7 +341,7 @@ enum XsnsFunctions {FUNC_SETTINGS_OVERRIDE, FUNC_PIN_STATE, FUNC_MODULE_INIT, FU FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_SET_DEVICE_POWER, FUNC_SHOW_SENSOR, FUNC_ANY_KEY, FUNC_ENERGY_EVERY_SECOND, FUNC_ENERGY_RESET, - FUNC_RULES_PROCESS, FUNC_TELEPERIOD_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM, FUNC_BUTTON_PRESSED, + FUNC_RULES_PROCESS, FUNC_TELEPERIOD_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM, FUNC_BUTTON_PRESSED, FUNC_BUTTON_MULTI_PRESSED, FUNC_WEB_ADD_BUTTON, FUNC_WEB_ADD_CONSOLE_BUTTON, FUNC_WEB_ADD_MANAGEMENT_BUTTON, FUNC_WEB_ADD_MAIN_BUTTON, FUNC_WEB_ADD_HANDLER, FUNC_SET_CHANNELS, FUNC_SET_SCHEME, FUNC_HOTPLUG_SCAN, FUNC_DEVICE_GROUP_ITEM }; diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index a4f2c3e7e..f032b8b67 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -3205,6 +3205,9 @@ bool Xdrv04(uint8_t function) case FUNC_SET_POWER: LightSetPower(); break; + case FUNC_BUTTON_MULTI_PRESSED: + result = XlgtCall(FUNC_BUTTON_MULTI_PRESSED); + break; case FUNC_COMMAND: result = DecodeCommand(kLightCommands, LightCommand, kLightSynonyms); if (!result) { From f53e9462b3c01c882aacf0737ae1c2ee073a2c7d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 30 Nov 2021 15:43:43 +0100 Subject: [PATCH 161/185] Bump version to 10.0.0.4 --- CHANGELOG.md | 21 ++++++++++++++------- RELEASENOTES.md | 20 +++++++++++++++----- tasmota/tasmota_version.h | 2 +- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3b35f9f4..ef27a353a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,19 +3,26 @@ All notable changes to this project will be documented in this file. ## [Unreleased] - Development -## [10.0.0.3] +## [10.0.0.4] +### Added +- (Internal) Support for FUNC_BUTTON_MULTI_PRESSED in (light)drivers + +### Changed +- (Internal) Range conversion edge values + +## [10.0.0.3] 20211130 ### Added - Shutter support for venetian blinds with tilt control -- Autoconfiguration for ESP32 and variants +- ESP32 Autoconfiguration - ESP32 fix leftover GPIO configuration after restart - ESP32 Proof of Concept Sonoff SPM with limited functionality (switching and energy monitoring) (#13447) - WS2812 scheme 13 stairs effect (#13595) -- Preliminary support for Tasmota Apps (.tapp extesions) -- Berry support for neopixel (WS2812, SK6812) +- ESP32 Preliminary support for Tasmota Apps (.tapp extesions) +- ESP32 Berry support for neopixel (WS2812, SK6812) - Command ``IfxPeriod `` to overrule ``Teleperiod`` for Influx messages (#13750) -- OTA over HTTPS (ESP32x only) -- Berry add ``import re`` regex module -- Add HTTPS support to ``WebQuery`` (ESP32x only) +- ESP32 OTA over HTTPS +- ESP32 Berry ``import re`` regex module +- ESP32 HTTPS support to ``WebQuery`` ### Changed - ESP8266 Gratuitous ARP enabled and set to 60 seconds (#13623) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 985262bd6..efd16218c 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -100,23 +100,33 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo [Complete list](BUILDS.md) of available feature and sensors. -## Changelog v10.0.0.3 +## Changelog v10.0.0.4 ### Added - 1 second heartbeat GPIO -- ESP32 Berry add module ``python_compat`` to be closer to Python syntax [#13428](https://github.com/arendst/Tasmota/issues/13428) -- ESP32 Proof of Concept Sonoff SPM with limited functionality (switching and energy monitoring) [#13447](https://github.com/arendst/Tasmota/issues/13447) +- (Internal) Support for FUNC_BUTTON_MULTI_PRESSED in (light)drivers - Command ``TcpConfig`` for TCPBridge protocol configuration [#13565](https://github.com/arendst/Tasmota/issues/13565) - Support for HDC2010 temperature/humidity sensor by Luc Boudreau [#13633](https://github.com/arendst/Tasmota/issues/13633) - WS2812 scheme 13 stairs effect [#13595](https://github.com/arendst/Tasmota/issues/13595) - Command ``IfxPeriod `` to overrule ``Teleperiod`` for Influx messages [#13750](https://github.com/arendst/Tasmota/issues/13750) +- Shutter support for venetian blinds with tilt control +- ESP32 Proof of Concept Sonoff SPM with limited functionality (switching and energy monitoring) [#13447](https://github.com/arendst/Tasmota/issues/13447) +- ESP32 Autoconfiguration +- ESP32 Preliminary support for Tasmota Apps (.tapp extesions) +- ESP32 OTA over HTTPS +- ESP32 HTTPS support to ``WebQuery`` +- ESP32 Berry support for neopixel (WS2812, SK6812) +- ESP32 Berry ``import re`` regex module +- ESP32 Berry add module ``python_compat`` to be closer to Python syntax [#13428](https://github.com/arendst/Tasmota/issues/13428) ### Breaking Changed - ESP32-S2 TSettings memory usage fixed to 4096 bytes regression from v9.5.0.8 ### Changed -- ESP32 core library from v1.0.7.4 to v2.0.1 -- ESP32-C3 core library from v2.0.0-post to v2.0.1 +- ESP32 core library from v1.0.7.4 to v2.0.1.1 +- ESP32-C3 core library from v2.0.0-post to ESP32 core library - IRremoteESP8266 library from v2.7.20 to v2.8.0 +- (Internal) Range conversion edge values +- ESP8266 Gratuitous ARP enabled and set to 60 seconds (#13623) - File editor no-wrap [#13427](https://github.com/arendst/Tasmota/issues/13427) - ESP8266 Gratuitous ARP enabled and set to 60 seconds [#13623](https://github.com/arendst/Tasmota/issues/13623) - Ethernet hostname ending in ``_eth`` to ``-eth`` according to RFC952 diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index 7e3e74d42..be18bd75e 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,6 +20,6 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x0A000003; +const uint32_t VERSION = 0x0A000004; #endif // _TASMOTA_VERSION_H_ From 3535b7543edbcfc28950571f8032f1f33f98f189 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 30 Nov 2021 16:03:57 +0100 Subject: [PATCH 162/185] Add support for GPE Multi color smart light Add support for GPE Multi color smart light as sold by Action in the Netherlands --- CHANGELOG.md | 4 + RELEASENOTES.md | 4 +- tasmota/my_user_config.h | 1 + tasmota/support_features.ino | 4 +- tasmota/xlgt_07_lsc_mcsl.ino | 257 +++++++++++++++++++++++++++++++++++ tools/decode-status.py | 7 +- 6 files changed, 272 insertions(+), 5 deletions(-) create mode 100644 tasmota/xlgt_07_lsc_mcsl.ino diff --git a/CHANGELOG.md b/CHANGELOG.md index ef27a353a..fc66c661a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,10 +6,14 @@ All notable changes to this project will be documented in this file. ## [10.0.0.4] ### Added - (Internal) Support for FUNC_BUTTON_MULTI_PRESSED in (light)drivers +- Support for GPE Multi color smart light as sold by Action in the Netherlands ### Changed - (Internal) Range conversion edge values +### Fixed +- Tuya dimmer range issue (#13849) + ## [10.0.0.3] 20211130 ### Added - Shutter support for venetian blinds with tilt control diff --git a/RELEASENOTES.md b/RELEASENOTES.md index efd16218c..8c8578f3e 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -108,6 +108,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo - Support for HDC2010 temperature/humidity sensor by Luc Boudreau [#13633](https://github.com/arendst/Tasmota/issues/13633) - WS2812 scheme 13 stairs effect [#13595](https://github.com/arendst/Tasmota/issues/13595) - Command ``IfxPeriod `` to overrule ``Teleperiod`` for Influx messages [#13750](https://github.com/arendst/Tasmota/issues/13750) +- Support for GPE Multi color smart light as sold by Action in the Netherlands - Shutter support for venetian blinds with tilt control - ESP32 Proof of Concept Sonoff SPM with limited functionality (switching and energy monitoring) [#13447](https://github.com/arendst/Tasmota/issues/13447) - ESP32 Autoconfiguration @@ -126,7 +127,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo - ESP32-C3 core library from v2.0.0-post to ESP32 core library - IRremoteESP8266 library from v2.7.20 to v2.8.0 - (Internal) Range conversion edge values -- ESP8266 Gratuitous ARP enabled and set to 60 seconds (#13623) +- ESP8266 Gratuitous ARP enabled and set to 60 seconds [#13623](https://github.com/arendst/Tasmota/issues/13623) - File editor no-wrap [#13427](https://github.com/arendst/Tasmota/issues/13427) - ESP8266 Gratuitous ARP enabled and set to 60 seconds [#13623](https://github.com/arendst/Tasmota/issues/13623) - Ethernet hostname ending in ``_eth`` to ``-eth`` according to RFC952 @@ -139,6 +140,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo - Discovery of shutters [#13572](https://github.com/arendst/Tasmota/issues/13572) - ESP32-C3 OneWire as used by DS18x20 [#13583](https://github.com/arendst/Tasmota/issues/13583) - ESP32 analog NTC temperature calculation [#13703](https://github.com/arendst/Tasmota/issues/13703) +- Tuya dimmer range issue [#13849](https://github.com/arendst/Tasmota/issues/13849) ### Removed - ILI9488 driver in favour of Universal Display driver [#13719](https://github.com/arendst/Tasmota/issues/13719) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index d9eb64830..923e19108 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -553,6 +553,7 @@ #define USE_LIGHT_PALETTE // Add support for color palette (+0k7 code) #define USE_LIGHT_VIRTUAL_CT // Add support for Virtual White Color Temperature (+1.1k code) #define USE_DGR_LIGHT_SEQUENCE // Add support for device group light sequencing (requires USE_DEVICE_GROUPS) (+0k2 code) +//#define USE_LSC_MCSL // Add support for GPE Multi color smart light as sold by Action in the Netherlands (+1k1 code) // -- Counter input ------------------------------- #define USE_COUNTER // Enable inputs as counter (+0k8 code) diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino index 9236a511b..59d12e666 100644 --- a/tasmota/support_features.ino +++ b/tasmota/support_features.ino @@ -778,7 +778,9 @@ void ResponseAppendFeatures(void) #if defined(USE_I2C) && defined(USE_HDC2010) feature8 |= 0x00010000; // xsns_94_hdc2010.ino #endif -// feature8 |= 0x00020000; +#if defined(USE_LIGHT) && defined(USE_LSC_MCSL) + feature8 |= 0x00020000; // xlgt_07_lsc_mcsl.ino +#endif // feature8 |= 0x00040000; // feature8 |= 0x00080000; diff --git a/tasmota/xlgt_07_lsc_mcsl.ino b/tasmota/xlgt_07_lsc_mcsl.ino new file mode 100644 index 000000000..4f71c866f --- /dev/null +++ b/tasmota/xlgt_07_lsc_mcsl.ino @@ -0,0 +1,257 @@ +/* + xlgt_07_lsc_mcsl.ino - GPE Multi color smart light support for Tasmota + + Copyright (C) 2021 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifdef USE_LIGHT +#ifdef USE_LSC_MCSL +/*********************************************************************************************\ + * Golden Power Electronics Integrated Switching Power Supply with Built-in Controller + * GP-SW084-052 uses an ESP8285 (TYWE2S) and submicrocontroller controlling two wire RGB leds + * https://www.gp-electronic.com/product/integrated-switching-power-supply-with-built-in-controller/eugs/european-vertical-6w8-function.html + * + * {"NAME":"LSC MC Lights","GPIO":[1,1,1,1,544,32,1,1,3840,1,3872,1,1,1],"FLAG":0,"BASE":18} + * + * NL: Action LSC Multi color smart lights + * + * Button usage: + * Single press = Power On / Off + * Double press = Cycle Colors + * Triple press = Cycle Effects + * + * HSBColor Color + * ---------- ----------- + * 1 .. 45 R (Red) + * 46 .. 90 RG (Yellow) + * 91 .. 135 G (Green) + * 136 .. 179 GB (Light Blue) + * 180 .. 224 B (Blue) + * 225 .. 269 RB (Purple) + * 270 .. 314 RGB (White) + * 315 .. 360 (Alternating) + * + * Dimmer Effect + * ---------- --------------------------- + * 0 .. 12 Bright (Steady On) + * 13 .. 24 Gradually (Slow Fade) + * 25 .. 37 Star (Sequential) + * 38 .. 49 Flower (In Waves) + * 50 .. 62 Marquee (Chasing / Flash) + * 63 .. 74 Fireworks (Twinkle / Flash) + * 75 .. 87 Meteor + * 88 .. 100 Stream + * + * GPIO04 = Green led + * GPIO05 = Button + * GPIO12 = Data to submicrocontroller + * GPIO14 = Reset to submicrocontroller (26ms active high) +\*********************************************************************************************/ + +#define XLGT_07 7 + +#define LSCMC_GPIO_DATA 12 +#define LSCMC_GPIO_RESET 14 + +#define LSCMC_BIT_TIME 600 // us + +const uint16_t kLscMcData[] PROGMEM = { + //R RG G GB B RB RGB RGBa + 0x0F4D, 0x0745, 0x08B5, 0x0340, 0x0CB0, 0x04B8, 0x0B48, 0x0143, // Bright (Steady on) + 0x8FED, 0x87E5, 0x8815, 0x83E0, 0x8C10, 0x8418, 0x8BE8, 0x81E3, // Gradually (Slow Fade) + 0x70ED, 0x78E5, 0x7715, 0x7CE0, 0x7510, 0x7B18, 0x74E8, 0x7EE3, // Star (Sequential) + 0xCF92, 0xC79A, 0xC86A, 0xC39F, 0xCC6F, 0xC467, 0xCB97, 0xC19C, // Flower (In Waves) + 0x3093, 0x389A, 0x376A, 0x3C9F, 0x336F, 0x3B67, 0x3497, 0x3E9C, // Marquee (Chasing / Flash) + 0xB02D, 0xB825, 0xB7D5, 0xBC20, 0xB3D0, 0xBBD8, 0xB428, 0xBE23, // Fireworks (Twinkle / Flash) + 0x4F2D, 0x4725, 0x48D5, 0x4320, 0x4CD0, 0x44D8, 0x4B28, 0x4123, // Meteor + 0xEFAD, 0xE7A5, 0xE855, 0xE3A1, 0xEC50, 0xE458, 0xEBA8, 0xE1A3 // Stream +}; + +#include +Ticker LscMcStartDelay; + +struct LSCMC { + uint32_t last_send; + uint8_t function; + uint8_t color; + uint8_t dimmer; + uint8_t power; + uint8_t scheme_offset; + uint8_t pin; +} Lscmc; + +/*********************************************************************************************/ + +void LscMcSend(void) { + Lscmc.function &= 0x7; + Lscmc.color &= 0x7; + uint16_t fc = pgm_read_word(kLscMcData + (8 * Lscmc.function) + Lscmc.color); + + uint32_t data; + if (Lscmc.power) { + data = 0xC2FF0000 | fc; + } else { + data = Lscmc.last_send & 0xFF00FFFF; + data ^= 0x0000FF00; + } + + if (data == Lscmc.last_send) { return; } + + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("LSC: Function %d, Color %d, State %d, Send %08X"), + Lscmc.function, Lscmc.color, Lscmc.power, data); + + Lscmc.last_send = data; + + digitalWrite(Lscmc.pin, LOW); + delayMicroseconds(LSCMC_BIT_TIME * 15); + digitalWrite(Lscmc.pin, HIGH); + delayMicroseconds(LSCMC_BIT_TIME * 7 + (LSCMC_BIT_TIME / 2)); + digitalWrite(Lscmc.pin, LOW); + delayMicroseconds(LSCMC_BIT_TIME); + digitalWrite(Lscmc.pin, HIGH); + bool last_bit = 0; + bool bit = 0; + uint32_t bit_mask = 0x80000000; + for (uint32_t i = 0; i < 32; i++) { + bit = (data & bit_mask); + if (bit != last_bit) { + delayMicroseconds(LSCMC_BIT_TIME * 3); // Switch bit state + } else { + delayMicroseconds(LSCMC_BIT_TIME); + } + digitalWrite(Lscmc.pin, LOW); + delayMicroseconds(LSCMC_BIT_TIME); + digitalWrite(Lscmc.pin, HIGH); + last_bit = bit; + bit_mask >>= 1; + } +} + +/*********************************************************************************************/ + +bool LscMcSetChannelsFromFunc(void) { + // Use power for Off / On + uint8_t power = Light.power; + bool power_changed = (Lscmc.power != power); + Lscmc.power = power; + + // Use dimmer for function + uint8_t dimmer = light_state.getDimmer(); +/* + dimmer = changeUIntScale(dimmer, 0, 100, 0, 3); + dimmer = changeUIntScale(dimmer, 0, 3, 0, 255); + bool dimmer_changed = (Lscmc.dimmer != dimmer); + Lscmc.dimmer= dimmer; +*/ + uint8_t function = changeUIntScale(dimmer, 0, 100, 0, 7); + bool function_changed = (Lscmc.function != function); + Lscmc.function = function; + + uint16_t hue; + uint8_t sat; + LightGetHSB(&hue, &sat, nullptr); +/* + // Use saturation for function (won't work as if sat = 0 this function is not called) + uint8_t function = changeUIntScale(sat, 0, 255, 0, 7); + bool function_changed = (Lscmc.function != function); + Lscmc.function = function; +*/ + // Use hue for color + uint8_t color = changeUIntScale(hue, 1, 359, 0, 7); + bool color_changed = (Lscmc.color != color); + Lscmc.color = color; + +// AddLog(LOG_LEVEL_DEBUG, PSTR("LSC: Power %d, Hue %d = Color %d, Dimmer %d = Function %d"), +// Lscmc.power, hue, Lscmc.color, dimmer, Lscmc.function); + + if (!power_changed && !function_changed && !color_changed) { return true; } + + static bool first_call = true; + if (first_call) { + LscMcStartDelay.once_ms(900, LscMcSend); // Allow startup time for microcontroller + first_call = false; + } else { + LscMcSend(); + } + + return true; +} + +bool LscMcMultiButtonPressed(void) { + if (XdrvMailbox.index != 0) { return false; } // button_index + + char command[20]; + + uint32_t press_counter = XdrvMailbox.payload; + if (2 == press_counter) { // Color rotate + uint32_t color = Lscmc.color +1; + if (color > 7) { color = 0; } + snprintf_P(command, sizeof(command), PSTR(D_CMND_HSBCOLOR " %d"), (color * (360 / 8)) + ((360 / 8) / 2)); + ExecuteCommand(command, SRC_BUTTON); + } else if (3 == press_counter) { // Function rotate + uint32_t function = Lscmc.function +1; + if (function > 7) { function = 0; } + snprintf_P(command, sizeof(command), PSTR(D_CMND_DIMMER " %d"), (function * (100 / 8)) + ((100 / 8) / 2)); + ExecuteCommand(command, SRC_BUTTON); + } + return true; +} + +void LscMcModuleSelected(void) { + if (!ValidTemplate(PSTR("LSC MC Lights"))) { return; } + if (!PinUsed(GPIO_OUTPUT_HI) || !PinUsed(GPIO_OUTPUT_LO)) { return; } + + Lscmc.pin = Pin(GPIO_OUTPUT_HI); + + uint32_t pin_reset = Pin(GPIO_OUTPUT_LO); + digitalWrite(pin_reset, HIGH); + delay(26); + digitalWrite(pin_reset, LOW); + + Settings->flag.button_single = 0; // SetOption13 - We need multi press detection + Settings->flag3.slider_dimmer_stay_on = 1; // SetOption77 - We need dimmer to keep power on at 0 + + Lscmc.last_send = 0xC2FFEBA8; + + TasmotaGlobal.light_type = LT_RGB; + TasmotaGlobal.light_driver = XLGT_07; +// AddLog(LOG_LEVEL_DEBUG, PSTR("LGT: LSC Multi Color Found")); +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xlgt07(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_SET_CHANNELS: + result = LscMcSetChannelsFromFunc(); + break; + case FUNC_BUTTON_MULTI_PRESSED: + result = LscMcMultiButtonPressed(); + break; + case FUNC_MODULE_INIT: + LscMcModuleSelected(); + break; + } + return result; +} + +#endif // USE_LSC_MCSL +#endif // USE_LIGHT \ No newline at end of file diff --git a/tools/decode-status.py b/tools/decode-status.py index f6d8a9b36..1ca16c0ab 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -185,7 +185,8 @@ a_setoption = [[ "(Web) Allow access without referer check", "(Energy) Show phase information", "(Debug) Show heap with logging timestamp", - "","","", + "(Tuya) Allow save dimmer = 0 receved by MCU", + "","", "","","","", "","","","", "","","","" @@ -259,7 +260,7 @@ a_features = [[ "USE_BM8563","USE_ENERGY_DUMMY","USE_AM2320","USE_T67XX", "USE_MCP2515","USE_TASMESH","USE_WIFI_RANGE_EXTENDER","USE_INFLUXDB", "USE_HRG15","USE_VINDRIKTNING","USE_SCD40","USE_HM330X", - "USE_HDC2010","","","", + "USE_HDC2010","USE_LSC_MCSL","","", "","","","", "","","","", "","","","" @@ -290,7 +291,7 @@ else: obj = json.load(fp) def StartDecode(): - print ("\n*** decode-status.py v20211111 by Theo Arends and Jacek Ziolkowski ***") + print ("\n*** decode-status.py v20211130 by Theo Arends and Jacek Ziolkowski ***") # print("Decoding\n{}".format(obj)) From 838ac68a84b41d0ecf682f4c2b62f41c27962b9b Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 30 Nov 2021 18:27:13 +0100 Subject: [PATCH 163/185] ZigBee serial: always initialize RST pins (for TCP serial server) --- tasmota/xdrv_23_zigbee_9_serial.ino | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/tasmota/xdrv_23_zigbee_9_serial.ino b/tasmota/xdrv_23_zigbee_9_serial.ino index 3eaea4048..2d054aebb 100644 --- a/tasmota/xdrv_23_zigbee_9_serial.ino +++ b/tasmota/xdrv_23_zigbee_9_serial.ino @@ -282,6 +282,17 @@ void ZigbeeInputLoop(void) { void ZigbeeInitSerial(void) { zigbee.active = false; + + // always initialize reset pins for TCP serial server + if (PinUsed(GPIO_ZIGBEE_RST)) { + pinMode(Pin(GPIO_ZIGBEE_RST), OUTPUT); + digitalWrite(Pin(GPIO_ZIGBEE_RST), 1); + } + if (PinUsed(GPIO_ZIGBEE_RST, 1)) { + pinMode(Pin(GPIO_ZIGBEE_RST, 1), OUTPUT); + digitalWrite(Pin(GPIO_ZIGBEE_RST, 1), 1); + } + if (PinUsed(GPIO_ZIGBEE_RX) && PinUsed(GPIO_ZIGBEE_TX)) { AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "GPIOs Rx:%d Tx:%d"), Pin(GPIO_ZIGBEE_RX), Pin(GPIO_ZIGBEE_TX)); // if TasmotaGlobal.seriallog_level is 0, we allow GPIO 13/15 to switch to Hardware Serial @@ -295,15 +306,6 @@ void ZigbeeInitSerial(void) zigbee_buffer = new SBuffer(ZIGBEE_BUFFER_SIZE); } - if (PinUsed(GPIO_ZIGBEE_RST)) { - pinMode(Pin(GPIO_ZIGBEE_RST), OUTPUT); - digitalWrite(Pin(GPIO_ZIGBEE_RST), 1); - } - if (PinUsed(GPIO_ZIGBEE_RST, 1)) { - pinMode(Pin(GPIO_ZIGBEE_RST, 1), OUTPUT); - digitalWrite(Pin(GPIO_ZIGBEE_RST, 1), 1); - } - zigbee.active = true; zigbee.init_phase = true; // start the state machine zigbee.state_machine = true; // start the state machine From 768335e1f04cef647bf2fec395207010c5124b22 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 30 Nov 2021 21:58:40 +0100 Subject: [PATCH 164/185] Update nimble --- lib/libesp32_div/NimBLE-Arduino/CHANGELOG.md | 13 + .../NimBLE_Secure_Client.ino | 182 +- .../NimBLE_Secure_Server.ino | 74 +- lib/libesp32_div/NimBLE-Arduino/library.json | 2 +- .../NimBLE-Arduino/library.properties | 2 +- .../NimBLE-Arduino/src/NimBLE2904.cpp | 8 +- .../NimBLE-Arduino/src/NimBLE2904.h | 8 +- .../NimBLE-Arduino/src/NimBLEAddress.cpp | 2 +- .../NimBLE-Arduino/src/NimBLEAddress.h | 7 +- .../src/NimBLEAdvertisedDevice.cpp | 8 +- .../src/NimBLEAdvertisedDevice.h | 13 +- .../NimBLE-Arduino/src/NimBLEAdvertising.cpp | 19 +- .../NimBLE-Arduino/src/NimBLEAdvertising.h | 13 +- .../NimBLE-Arduino/src/NimBLEBeacon.cpp | 2 +- .../src/NimBLECharacteristic.cpp | 33 +- .../NimBLE-Arduino/src/NimBLECharacteristic.h | 14 +- .../NimBLE-Arduino/src/NimBLEClient.cpp | 59 +- .../NimBLE-Arduino/src/NimBLEClient.h | 11 +- .../NimBLE-Arduino/src/NimBLEDescriptor.cpp | 24 +- .../NimBLE-Arduino/src/NimBLEDescriptor.h | 8 +- .../NimBLE-Arduino/src/NimBLEDevice.cpp | 197 +- .../NimBLE-Arduino/src/NimBLEDevice.h | 21 +- .../NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp | 16 +- .../NimBLE-Arduino/src/NimBLEEddystoneTLM.h | 1 + .../NimBLE-Arduino/src/NimBLEEddystoneURL.cpp | 2 +- .../NimBLE-Arduino/src/NimBLEHIDDevice.cpp | 9 +- .../NimBLE-Arduino/src/NimBLEHIDDevice.h | 9 +- .../NimBLE-Arduino/src/NimBLELog.h | 92 +- .../src/NimBLERemoteCharacteristic.cpp | 18 +- .../src/NimBLERemoteCharacteristic.h | 8 +- .../src/NimBLERemoteDescriptor.cpp | 8 +- .../src/NimBLERemoteDescriptor.h | 7 +- .../src/NimBLERemoteService.cpp | 8 +- .../NimBLE-Arduino/src/NimBLERemoteService.h | 7 +- .../NimBLE-Arduino/src/NimBLEScan.cpp | 7 +- .../NimBLE-Arduino/src/NimBLEScan.h | 11 +- .../NimBLE-Arduino/src/NimBLESecurity.cpp | 2 +- .../NimBLE-Arduino/src/NimBLESecurity.h | 8 +- .../NimBLE-Arduino/src/NimBLEServer.cpp | 51 +- .../NimBLE-Arduino/src/NimBLEServer.h | 12 +- .../NimBLE-Arduino/src/NimBLEService.cpp | 23 +- .../NimBLE-Arduino/src/NimBLEService.h | 14 +- .../NimBLE-Arduino/src/NimBLEUUID.cpp | 3 +- .../NimBLE-Arduino/src/NimBLEUUID.h | 8 +- .../NimBLE-Arduino/src/NimBLEUtils.cpp | 11 +- .../NimBLE-Arduino/src/NimBLEUtils.h | 7 +- .../NimBLE-Arduino/src/console/console.h | 21 - .../NimBLE-Arduino/src/esp_compiler.h | 33 - .../src/{ => nimble}/CODING_STANDARDS.md | 0 .../NimBLE-Arduino/src/nimble/LICENSE | 217 + .../NimBLE-Arduino/src/{ => nimble}/NOTICE | 3 +- .../NimBLE-Arduino/src/{ => nimble}/README.md | 16 +- .../src/{ => nimble}/RELEASE_NOTES.md | 20 +- .../src/nimble/console/console.h | 16 + .../esp_port/esp-hci/include/esp_compiler.h | 51 + .../esp-hci/include}/esp_nimble_hci.h | 4 +- .../esp_port}/esp-hci/src/esp_nimble_hci.c | 30 +- .../esp_port/port/include}/esp_nimble_cfg.h | 0 .../esp_port/port/include}/esp_nimble_mem.h | 0 .../esp_port}/port/src/esp_nimble_mem.c | 4 +- .../src/{ => nimble}/ext/tinycrypt/AUTHORS | 0 .../src/{ => nimble}/ext/tinycrypt/LICENSE | 0 .../src/{ => nimble}/ext/tinycrypt/README | 0 .../src/{ => nimble}/ext/tinycrypt/VERSION | 0 .../ext/tinycrypt/documentation/tinycrypt.rst | 0 .../ext/tinycrypt/include}/tinycrypt/aes.h | 0 .../tinycrypt/include}/tinycrypt/cbc_mode.h | 2 +- .../tinycrypt/include}/tinycrypt/ccm_mode.h | 2 +- .../tinycrypt/include}/tinycrypt/cmac_mode.h | 2 +- .../tinycrypt/include}/tinycrypt/constants.h | 0 .../tinycrypt/include}/tinycrypt/ctr_mode.h | 4 +- .../tinycrypt/include}/tinycrypt/ctr_prng.h | 2 +- .../ext/tinycrypt/include}/tinycrypt/ecc.h | 0 .../ext/tinycrypt/include}/tinycrypt/ecc_dh.h | 2 +- .../tinycrypt/include}/tinycrypt/ecc_dsa.h | 2 +- .../tinycrypt/ecc_platform_specific.h | 0 .../ext/tinycrypt/include}/tinycrypt/hmac.h | 2 +- .../tinycrypt/include}/tinycrypt/hmac_prng.h | 4 +- .../ext/tinycrypt/include}/tinycrypt/sha256.h | 0 .../ext/tinycrypt/include}/tinycrypt/utils.h | 0 .../ext/tinycrypt/src/aes_decrypt.c | 6 +- .../ext/tinycrypt/src/aes_encrypt.c | 6 +- .../{ => nimble}/ext/tinycrypt/src/cbc_mode.c | 6 +- .../{ => nimble}/ext/tinycrypt/src/ccm_mode.c | 6 +- .../ext/tinycrypt/src/cmac_mode.c | 8 +- .../{ => nimble}/ext/tinycrypt/src/ctr_mode.c | 6 +- .../{ => nimble}/ext/tinycrypt/src/ctr_prng.c | 6 +- .../src/{ => nimble}/ext/tinycrypt/src/ecc.c | 4 +- .../{ => nimble}/ext/tinycrypt/src/ecc_dh.c | 6 +- .../{ => nimble}/ext/tinycrypt/src/ecc_dsa.c | 6 +- .../ext/tinycrypt/src/ecc_platform_specific.c | 0 .../src/{ => nimble}/ext/tinycrypt/src/hmac.c | 6 +- .../ext/tinycrypt/src/hmac_prng.c | 8 +- .../{ => nimble}/ext/tinycrypt/src/sha256.c | 6 +- .../{ => nimble}/ext/tinycrypt/src/utils.c | 4 +- .../src/nimble/host/mesh/src/ble_att_priv.h | 307 - .../nimble/host/mesh/src/ble_hs_conn_priv.h | 128 - .../nimble/host/mesh/src/ble_l2cap_coc_priv.h | 85 - .../src/nimble/host/mesh/src/ble_l2cap_priv.h | 125 - .../nimble/host/mesh/src/ble_l2cap_sig_priv.h | 124 - .../nimble/host/mesh/src/src/ble_att_priv.h | 301 - .../nimble/host/mesh/src/src/ble_gatt_priv.h | 199 - .../host/mesh/src/src/ble_hs_hci_priv.h | 124 - .../host/mesh/src/src/ble_l2cap_coc_priv.h | 106 - .../nimble/host/mesh/src/src/ble_l2cap_priv.h | 144 - .../host/mesh/src/src/ble_l2cap_sig_priv.h | 184 - .../nimble/host/mesh/src/src/ble_sm_priv.h | 428 -- .../src/nimble/host/mesh/src/testing.c | 200 - .../src/nimble/host/mesh/src/testing.h | 23 - .../src/nimble/host/src/ble_att_cmd_priv.h | 449 -- .../src/nimble/host/src/ble_gap_priv.h | 154 - .../src/nimble/host/src/ble_gatt_priv.h | 199 - .../src/nimble/host/src/ble_hs_adv_priv.h | 36 - .../src/nimble/host/src/ble_hs_conn_priv.h | 148 - .../src/nimble/host/src/ble_hs_hci_priv.h | 124 - .../src/nimble/host/src/ble_hs_id_priv.h | 45 - .../host/src/ble_hs_periodic_sync_priv.h | 55 - .../src/nimble/host/src/ble_hs_priv.h | 157 - .../src/nimble/host/src/ble_hs_resolv_priv.h | 111 - .../src/nimble/host/src/ble_monitor_priv.h | 100 - .../nimble/host/store/ram/src/ble_store_ram.c | 497 -- .../controller/include/controller/ble_hw.h | 116 + .../controller/include/controller/ble_ll.h | 584 ++ .../include/controller/ble_ll_adv.h | 209 + .../include/controller/ble_ll_conn.h | 425 ++ .../include/controller/ble_ll_ctrl.h | 313 + .../include/controller/ble_ll_hci.h | 75 + .../include/controller/ble_ll_resolv.h | 116 + .../include/controller/ble_ll_rfmgmt.h | 63 + .../include/controller/ble_ll_scan.h | 293 + .../include/controller/ble_ll_sched.h | 216 + .../include/controller/ble_ll_sync.h | 74 + .../include/controller/ble_ll_test.h} | 8 +- .../include/controller/ble_ll_trace.h | 96 + .../include/controller/ble_ll_utils.h} | 27 +- .../include/controller/ble_ll_whitelist.h} | 36 +- .../controller/include/controller/ble_phy.h | 242 + .../include/controller/ble_phy_trace.h | 96 + .../src/nimble/nimble/controller/pkg.yml | 38 + .../src/nimble/nimble/controller/src/ble_ll.c | 1720 ++++++ .../nimble/nimble/controller/src/ble_ll_adv.c | 5143 +++++++++++++++++ .../nimble/controller/src/ble_ll_conn.c | 4279 ++++++++++++++ .../nimble/controller/src/ble_ll_conn_hci.c | 1898 ++++++ .../nimble/controller/src/ble_ll_conn_priv.h | 226 + .../nimble/controller/src/ble_ll_ctrl.c | 2747 +++++++++ .../nimble/nimble/controller/src/ble_ll_dtm.c | 728 +++ .../controller/src/ble_ll_dtm_priv.h} | 37 +- .../nimble/nimble/controller/src/ble_ll_hci.c | 1519 +++++ .../nimble/controller/src/ble_ll_hci_ev.c | 526 ++ .../controller/src/ble_ll_priv.h} | 34 +- .../nimble/controller/src/ble_ll_rand.c | 188 + .../nimble/controller/src/ble_ll_resolv.c | 755 +++ .../nimble/controller/src/ble_ll_rfmgmt.c | 348 ++ .../nimble/controller/src/ble_ll_scan.c | 3981 +++++++++++++ .../nimble/controller/src/ble_ll_sched.c | 1838 ++++++ .../nimble/controller/src/ble_ll_supp_cmd.c | 461 ++ .../nimble/controller/src/ble_ll_sync.c | 2248 +++++++ .../nimble/controller/src/ble_ll_trace.c | 56 + .../nimble/controller/src/ble_ll_utils.c | 303 + .../nimble/controller/src/ble_ll_whitelist.c | 297 + .../src/nimble/nimble/controller/syscfg.yml | 434 ++ .../drivers/nrf51/include/ble/xcvr.h} | 33 +- .../src/nimble/nimble/drivers/nrf51/pkg.yml | 31 + .../nimble/nimble/drivers/nrf51/src/ble_hw.c | 491 ++ .../nimble/nimble/drivers/nrf51/src/ble_phy.c | 1527 +++++ .../nimble/drivers/nrf52/include/ble/xcvr.h | 55 + .../src/nimble/nimble/drivers/nrf52/pkg.yml | 31 + .../nimble/nimble/drivers/nrf52/src/ble_hw.c | 491 ++ .../nimble/nimble/drivers/nrf52/src/ble_phy.c | 2120 +++++++ .../nimble/drivers/nrf52/src/ble_phy_trace.c | 47 + .../nimble/nimble/drivers/nrf52/syscfg.yml | 75 + .../nimble/host/include}/host/ble_att.h | 2 +- .../nimble/host/include}/host/ble_eddystone.h | 0 .../nimble/host/include}/host/ble_gap.h | 22 +- .../nimble/host/include}/host/ble_gatt.h | 4 +- .../nimble/host/include}/host/ble_hs.h | 34 +- .../nimble/host/include}/host/ble_hs_adv.h | 2 +- .../nimble/host/include}/host/ble_hs_hci.h | 0 .../nimble/host/include}/host/ble_hs_id.h | 2 +- .../nimble/host/include}/host/ble_hs_log.h | 4 +- .../nimble/host/include}/host/ble_hs_mbuf.h | 0 .../nimble/host/include}/host/ble_hs_pvcy.h | 2 +- .../nimble/host/include}/host/ble_hs_stop.h | 0 .../nimble/host/include}/host/ble_ibeacon.h | 0 .../nimble/host/include}/host/ble_l2cap.h | 2 +- .../nimble/host/include}/host/ble_monitor.h | 2 +- .../nimble/host/include}/host/ble_sm.h | 2 +- .../nimble/host/include}/host/ble_store.h | 2 +- .../nimble/host/include}/host/ble_uuid.h | 0 .../nimble/host/mesh/include}/mesh/access.h | 0 .../nimble/host/mesh/include}/mesh/cfg_cli.h | 0 .../nimble/host/mesh/include}/mesh/cfg_srv.h | 0 .../nimble/host/mesh/include}/mesh/glue.h | 35 +- .../host/mesh/include}/mesh/health_cli.h | 0 .../host/mesh/include}/mesh/health_srv.h | 0 .../nimble/host/mesh/include}/mesh/main.h | 0 .../nimble/host/mesh/include}/mesh/mesh.h | 4 +- .../host/mesh/include}/mesh/model_cli.h | 0 .../host/mesh/include}/mesh/model_srv.h | 0 .../nimble/host/mesh/include}/mesh/porting.h | 0 .../nimble/host/mesh/include}/mesh/proxy.h | 0 .../nimble/host/mesh/include}/mesh/slist.h | 0 .../nimble/host/mesh/include}/mesh/testing.h | 0 .../src/nimble/nimble/host/mesh/pkg.yml | 49 + .../{ => nimble}/host/mesh/src/access.c | 11 +- .../{ => nimble}/host/mesh/src/access.h | 2 +- .../nimble/{ => nimble}/host/mesh/src/adv.c | 23 +- .../nimble/{ => nimble}/host/mesh/src/adv.h | 2 +- .../{ => nimble}/host/mesh/src/atomic.h | 0 .../{ => nimble}/host/mesh/src/beacon.c | 9 +- .../{ => nimble}/host/mesh/src/beacon.h | 2 +- .../{ => nimble}/host/mesh/src/cfg_cli.c | 7 +- .../{ => nimble}/host/mesh/src/cfg_srv.c | 7 +- .../{ => nimble}/host/mesh/src/crypto.c | 16 +- .../{ => nimble}/host/mesh/src/crypto.h | 2 +- .../{ => nimble}/host/mesh/src/foundation.h | 0 .../{ => nimble}/host/mesh/src/friend.c | 11 +- .../{ => nimble}/host/mesh/src/friend.h | 2 +- .../nimble/{ => nimble}/host/mesh/src/glue.c | 10 +- .../{ => nimble}/host/mesh/src/health_cli.c | 9 +- .../{ => nimble}/host/mesh/src/health_srv.c | 7 +- .../{ => nimble}/host/mesh/src/light_model.c | 9 +- .../{ => nimble}/host/mesh/src/light_model.h | 4 +- .../nimble/{ => nimble}/host/mesh/src/lpn.c | 7 +- .../nimble/{ => nimble}/host/mesh/src/lpn.h | 2 +- .../nimble/{ => nimble}/host/mesh/src/mesh.c | 11 +- .../{ => nimble}/host/mesh/src/mesh_priv.h | 0 .../{ => nimble}/host/mesh/src/model_cli.c | 10 +- .../{ => nimble}/host/mesh/src/model_srv.c | 9 +- .../nimble/{ => nimble}/host/mesh/src/net.c | 38 +- .../nimble/{ => nimble}/host/mesh/src/net.h | 4 +- .../nimble/{ => nimble}/host/mesh/src/nodes.c | 7 +- .../nimble/{ => nimble}/host/mesh/src/nodes.h | 0 .../nimble/{ => nimble}/host/mesh/src/prov.c | 7 +- .../nimble/{ => nimble}/host/mesh/src/prov.h | 6 +- .../nimble/{ => nimble}/host/mesh/src/proxy.c | 13 +- .../nimble/{ => nimble}/host/mesh/src/proxy.h | 2 +- .../{ => nimble}/host/mesh/src/settings.c | 9 +- .../{ => nimble}/host/mesh/src/settings.h | 0 .../nimble/{ => nimble}/host/mesh/src/shell.c | 4 +- .../nimble/{ => nimble}/host/mesh/src/shell.h | 0 .../{ => nimble}/host/mesh/src/transport.c | 7 +- .../{ => nimble}/host/mesh/src/transport.h | 4 +- .../src/nimble/nimble/host/mesh/syscfg.yml | 661 +++ .../src/nimble/nimble/host/pkg.yml | 55 + .../src/nimble/nimble/host/pts/README.txt | 8 + .../src/nimble/nimble/host/pts/pts-gap.txt | 367 ++ .../src/nimble/nimble/host/pts/pts-gatt.txt | 508 ++ .../src/nimble/nimble/host/pts/pts-l2cap.txt | 304 + .../src/nimble/nimble/host/pts/pts-sm.txt | 310 + .../host/pts/tpg/94654-20170317-085122560.tpg | 1026 ++++ .../host/pts/tpg/94654-20170317-085441153.pts | 289 + .../ans/include}/services/ans/ble_svc_ans.h | 0 .../nimble/nimble/host/services/ans/pkg.yml | 34 + .../host/services/ans/src/ble_svc_ans.c | 10 +- .../nimble/host/services/ans/syscfg.yml | 30 + .../bas/include}/services/bas/ble_svc_bas.h | 0 .../nimble/nimble/host/services/bas/pkg.yml | 34 + .../host/services/bas/src/ble_svc_bas.c | 10 +- .../nimble/host/services/bas/syscfg.yml | 34 + .../dis/include/services/dis/ble_svc_dis.h | 113 + .../nimble/nimble/host/services/dis/pkg.yml | 34 + .../host/services/dis/src/ble_svc_dis.c | 331 ++ .../nimble/host/services/dis/syscfg.yml | 109 + .../gap/include}/services/gap/ble_svc_gap.h | 0 .../nimble/nimble/host/services/gap/pkg.yml | 34 + .../host/services/gap/src/ble_svc_gap.c | 8 +- .../nimble/host/services/gap/syscfg.yml | 83 + .../include}/services/gatt/ble_svc_gatt.h | 0 .../nimble/nimble/host/services/gatt/pkg.yml | 34 + .../host/services/gatt/src/ble_svc_gatt.c | 6 +- .../nimble/host/services/gatt/syscfg.yml | 24 + .../ias/include}/services/ias/ble_svc_ias.h | 0 .../nimble/nimble/host/services/ias/pkg.yml | 34 + .../host/services/ias/src/ble_svc_ias.c | 6 +- .../nimble/host/services/ias/syscfg.yml | 23 + .../include}/services/ipss/ble_svc_ipss.h | 0 .../nimble/nimble/host/services/ipss/pkg.yml | 35 + .../host/services/ipss/src/ble_svc_ipss.c | 6 +- .../nimble/host/services/ipss/syscfg.yml | 24 + .../lls/include}/services/lls/ble_svc_lls.h | 0 .../nimble/nimble/host/services/lls/pkg.yml | 34 + .../host/services/lls/src/ble_svc_lls.c | 6 +- .../nimble/host/services/lls/syscfg.yml | 22 + .../tps/include}/services/tps/ble_svc_tps.h | 0 .../nimble/nimble/host/services/tps/pkg.yml | 34 + .../host/services/tps/src/ble_svc_tps.c | 10 +- .../nimble/host/services/tps/syscfg.yml | 23 + .../nimble/{ => nimble}/host/src/ble_att.c | 0 .../{ => nimble}/host/src/ble_att_clt.c | 6 +- .../{ => nimble}/host/src/ble_att_cmd.c | 8 +- .../host}/src/ble_att_cmd_priv.h | 2 +- .../{ => nimble}/host/src/ble_att_priv.h | 8 +- .../{ => nimble}/host/src/ble_att_svr.c | 19 +- .../{ => nimble}/host/src/ble_eddystone.c | 6 +- .../nimble/{ => nimble}/host/src/ble_gap.c | 16 +- .../src => nimble/host}/src/ble_gap_priv.h | 6 +- .../mesh => nimble/host}/src/ble_gatt_priv.h | 6 +- .../nimble/{ => nimble}/host/src/ble_gattc.c | 8 +- .../nimble/{ => nimble}/host/src/ble_gatts.c | 31 +- .../{ => nimble}/host/src/ble_gatts_lcl.c | 6 +- .../src/nimble/{ => nimble}/host/src/ble_hs.c | 22 +- .../nimble/{ => nimble}/host/src/ble_hs_adv.c | 4 +- .../src => nimble/host}/src/ble_hs_adv_priv.h | 0 .../{ => nimble}/host/src/ble_hs_atomic.c | 0 .../host}/src/ble_hs_atomic_priv.h | 0 .../nimble/{ => nimble}/host/src/ble_hs_cfg.c | 4 +- .../{ => nimble}/host/src/ble_hs_conn.c | 6 +- .../host}/src/ble_hs_conn_priv.h | 0 .../{ => nimble}/host/src/ble_hs_flow.c | 4 +- .../host}/src/ble_hs_flow_priv.h | 0 .../nimble/{ => nimble}/host/src/ble_hs_hci.c | 8 +- .../{ => nimble}/host/src/ble_hs_hci_cmd.c | 59 +- .../{ => nimble}/host/src/ble_hs_hci_evt.c | 10 +- .../tps => nimble/host}/src/ble_hs_hci_priv.h | 2 +- .../{ => nimble}/host/src/ble_hs_hci_util.c | 4 +- .../nimble/{ => nimble}/host/src/ble_hs_id.c | 2 +- .../src => nimble/host}/src/ble_hs_id_priv.h | 0 .../nimble/{ => nimble}/host/src/ble_hs_log.c | 4 +- .../{ => nimble}/host/src/ble_hs_mbuf.c | 2 +- .../host}/src/ble_hs_mbuf_priv.h | 0 .../{ => nimble}/host/src/ble_hs_misc.c | 2 +- .../{ => nimble}/host/src/ble_hs_mqueue.c | 0 .../host/src/ble_hs_periodic_sync.c | 6 +- .../host}/src/ble_hs_periodic_sync_priv.h | 2 +- .../src => nimble/host}/src/ble_hs_priv.h | 8 +- .../{ => nimble}/host/src/ble_hs_pvcy.c | 4 +- .../host}/src/ble_hs_pvcy_priv.h | 0 .../{ => nimble}/host/src/ble_hs_resolv.c | 10 +- .../host}/src/ble_hs_resolv_priv.h | 0 .../{ => nimble}/host/src/ble_hs_shutdown.c | 2 +- .../{ => nimble}/host/src/ble_hs_startup.c | 4 +- .../host}/src/ble_hs_startup_priv.h | 0 .../{ => nimble}/host/src/ble_hs_stop.c | 8 +- .../{ => nimble}/host/src/ble_ibeacon.c | 2 +- .../nimble/{ => nimble}/host/src/ble_l2cap.c | 8 +- .../{ => nimble}/host/src/ble_l2cap_coc.c | 2 +- .../host/src/ble_l2cap_coc_priv.h | 8 +- .../{ => nimble}/host/src/ble_l2cap_priv.h | 8 +- .../{ => nimble}/host/src/ble_l2cap_sig.c | 4 +- .../{ => nimble}/host/src/ble_l2cap_sig_cmd.c | 0 .../host/src/ble_l2cap_sig_priv.h | 2 +- .../{ => nimble}/host/src/ble_monitor.c | 8 +- .../host}/src/ble_monitor_priv.h | 0 .../src/nimble/{ => nimble}/host/src/ble_sm.c | 6 +- .../nimble/{ => nimble}/host/src/ble_sm_alg.c | 16 +- .../nimble/{ => nimble}/host/src/ble_sm_cmd.c | 6 +- .../{ => nimble}/host/src/ble_sm_lgcy.c | 6 +- .../{ => nimble}/host/src/ble_sm_priv.h | 6 +- .../nimble/{ => nimble}/host/src/ble_sm_sc.c | 4 +- .../nimble/{ => nimble}/host/src/ble_store.c | 2 +- .../{ => nimble}/host/src/ble_store_util.c | 2 +- .../nimble/{ => nimble}/host/src/ble_uuid.c | 6 +- .../src => nimble/host}/src/ble_uuid_priv.h | 2 +- .../include}/store/config/ble_store_config.h | 0 .../nimble/nimble/host/store/config/pkg.yml | 38 + .../host/store/config/src/ble_store_config.c | 8 +- .../store/config/src/ble_store_config_conf.c | 296 + .../store/config/src/ble_store_config_priv.h | 0 .../host/store/config/src/ble_store_nvs.c | 11 +- .../nimble/host/store/config/syscfg.yml | 27 + .../src/nimble/nimble/host/syscfg.yml | 471 ++ .../nimble/nimble/host/tools/log2smtest.rb | 1029 ++++ .../host/util/include}/host/util/util.h | 0 .../src/nimble/nimble/host/util/pkg.yml | 29 + .../nimble/{ => nimble}/host/util/src/addr.c | 6 +- .../src/nimble/nimble/host/util/syscfg.yml | 19 + .../nimble/{ => nimble/include/nimble}/ble.h | 4 +- .../include/nimble}/ble_hci_trans.h | 2 +- .../{ => nimble/include/nimble}/hci_common.h | 0 .../{ => nimble/include/nimble}/nimble_npl.h | 5 +- .../{ => nimble/include/nimble}/nimble_opt.h | 2 +- .../include/nimble}/nimble_opt_auto.h | 2 +- .../NimBLE-Arduino/src/nimble/nimble/pkg.yml | 30 + .../src/nimble/nimble/syscfg.yml | 83 + .../src/nimble/nimble/transport/pkg.yml | 45 + .../ram/include/transport/ram/ble_hci_ram.h} | 11 +- .../src/nimble/nimble/transport/ram/pkg.yml | 36 + .../nimble/transport/ram/src/ble_hci_ram.c | 241 + .../nimble/nimble/transport/ram/syscfg.yml | 48 + .../src/nimble/nimble/transport/syscfg.yml | 68 + .../porting/nimble/include}/hal/hal_timer.h | 2 +- .../porting/nimble/include}/log/log.h | 0 .../nimble/include}/log_common/ignore.h | 0 .../nimble/include}/log_common/log_common.h | 10 +- .../porting/nimble/include}/logcfg/logcfg.h | 5 +- .../porting/nimble/include}/mem/mem.h | 0 .../porting/nimble/include}/modlog/modlog.h | 60 +- .../nimble/include/nimble}/nimble_port.h | 9 +- .../porting/nimble/include}/os/endian.h | 0 .../porting/nimble/include}/os/os.h | 14 +- .../porting/nimble/include}/os/os_cputime.h | 6 +- .../porting/nimble/include}/os/os_error.h | 2 +- .../porting/nimble/include}/os/os_mbuf.h | 2 +- .../porting/nimble/include}/os/os_mempool.h | 4 +- .../porting/nimble/include}/os/os_trace_api.h | 0 .../porting/nimble/include}/os/queue.h | 0 .../porting/nimble/include}/os/util.h | 0 .../porting/nimble/include}/stats/stats.h | 0 .../porting/nimble/include}/syscfg/syscfg.h | 6 +- .../nimble/include}/sysflash/sysflash.h | 0 .../porting/nimble/include}/sysinit/sysinit.h | 0 .../{ => nimble}/porting/nimble/src/endian.c | 2 +- .../porting/nimble/src/hal_timer.c | 11 +- .../src/{ => nimble}/porting/nimble/src/mem.c | 25 +- .../porting/nimble/src/nimble_port.c | 22 +- .../porting/nimble/src/os_cputime.c | 6 +- .../porting/nimble/src/os_cputime_pwr2.c | 2 +- .../{ => nimble}/porting/nimble/src/os_mbuf.c | 2 +- .../porting/nimble/src/os_mempool.c | 2 +- .../porting/nimble/src/os_msys_init.c | 19 +- .../freertos/include/nimble}/nimble_npl_os.h | 48 +- .../include/nimble}/nimble_port_freertos.h | 6 +- .../freertos/include/nimble}/npl_freertos.h | 8 +- .../npl/freertos/src/nimble_port_freertos.c | 40 +- .../npl/freertos/src/npl_os_freertos.c | 211 +- .../NimBLE-Arduino/src/nimconfig.h | 33 +- .../NimBLE-Arduino/src/src/ble_hs_hci_priv.h | 124 - .../NimBLE-Arduino/src/src/ble_sm_priv.h | 428 -- .../src/store/ram/ble_store_ram.h | 39 - .../NimBLE-Arduino/src/tinycrypt/AUTHORS | 15 - .../NimBLE-Arduino/src/tinycrypt/LICENSE | 61 - .../NimBLE-Arduino/src/tinycrypt/README | 71 - .../NimBLE-Arduino/src/tinycrypt/VERSION | 1 - .../src/tinycrypt/documentation/tinycrypt.rst | 352 -- 425 files changed, 46704 insertions(+), 6836 deletions(-) delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/console/console.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/esp_compiler.h rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/CODING_STANDARDS.md (100%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/LICENSE rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/NOTICE (61%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/README.md (90%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/RELEASE_NOTES.md (56%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/console/console.h create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/esp-hci/include/esp_compiler.h rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/esp_port/esp-hci/include}/esp_nimble_hci.h (98%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/esp_port}/esp-hci/src/esp_nimble_hci.c (96%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/esp_port/port/include}/esp_nimble_cfg.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/esp_port/port/include}/esp_nimble_mem.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/esp_port}/port/src/esp_nimble_mem.c (96%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/ext/tinycrypt/AUTHORS (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/ext/tinycrypt/LICENSE (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/ext/tinycrypt/README (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/ext/tinycrypt/VERSION (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/ext/tinycrypt/documentation/tinycrypt.rst (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/ext/tinycrypt/include}/tinycrypt/aes.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/ext/tinycrypt/include}/tinycrypt/cbc_mode.h (99%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/ext/tinycrypt/include}/tinycrypt/ccm_mode.h (99%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/ext/tinycrypt/include}/tinycrypt/cmac_mode.h (99%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/ext/tinycrypt/include}/tinycrypt/constants.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/ext/tinycrypt/include}/tinycrypt/ctr_mode.h (98%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/ext/tinycrypt/include}/tinycrypt/ctr_prng.h (99%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/ext/tinycrypt/include}/tinycrypt/ecc.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/ext/tinycrypt/include}/tinycrypt/ecc_dh.h (99%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/ext/tinycrypt/include}/tinycrypt/ecc_dsa.h (99%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/ext/tinycrypt/include}/tinycrypt/ecc_platform_specific.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/ext/tinycrypt/include}/tinycrypt/hmac.h (99%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/ext/tinycrypt/include}/tinycrypt/hmac_prng.h (99%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/ext/tinycrypt/include}/tinycrypt/sha256.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/ext/tinycrypt/include}/tinycrypt/utils.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/ext/tinycrypt/src/aes_decrypt.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/ext/tinycrypt/src/aes_encrypt.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/ext/tinycrypt/src/cbc_mode.c (96%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/ext/tinycrypt/src/ccm_mode.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/ext/tinycrypt/src/cmac_mode.c (97%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/ext/tinycrypt/src/ctr_mode.c (95%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/ext/tinycrypt/src/ctr_prng.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/ext/tinycrypt/src/ecc.c (99%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/ext/tinycrypt/src/ecc_dh.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/ext/tinycrypt/src/ecc_dsa.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/ext/tinycrypt/src/ecc_platform_specific.c (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/ext/tinycrypt/src/hmac.c (97%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/ext/tinycrypt/src/hmac_prng.c (97%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/ext/tinycrypt/src/sha256.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/ext/tinycrypt/src/utils.c (96%) delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_att_priv.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_hs_conn_priv.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_coc_priv.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_priv.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_sig_priv.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_priv.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gatt_priv.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_hci_priv.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_coc_priv.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_priv.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_sig_priv.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_sm_priv.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/testing.c delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/testing.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd_priv.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gap_priv.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gatt_priv.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv_priv.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn_priv.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_priv.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_id_priv.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync_priv.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_priv.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv_priv.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_monitor_priv.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/ram/src/ble_store_ram.c create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_hw.h create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll.h create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_adv.h create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_conn.h create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_ctrl.h create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_hci.h create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_resolv.h create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_rfmgmt.h create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_scan.h create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_sched.h create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_sync.h rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{host/src/ble_hs_startup_priv.h => nimble/controller/include/controller/ble_ll_test.h} (90%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_trace.h rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{host/src/ble_hs_mbuf_priv.h => nimble/controller/include/controller/ble_ll_utils.h} (58%) rename lib/libesp32_div/NimBLE-Arduino/src/{porting/nimble/include/nimble/nimble_port.h => nimble/nimble/controller/include/controller/ble_ll_whitelist.h} (54%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_phy.h create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_phy_trace.h create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/pkg.yml create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll.c create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_adv.c create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn.c create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn_hci.c create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn_priv.h create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_ctrl.c create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_dtm.c rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{host/src/ble_hs_atomic_priv.h => nimble/controller/src/ble_ll_dtm_priv.h} (53%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_hci.c create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_hci_ev.c rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{host/src/ble_uuid_priv.h => nimble/controller/src/ble_ll_priv.h} (54%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_rand.c create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_resolv.c create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_rfmgmt.c create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_scan.c create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_sched.c create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_supp_cmd.c create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_sync.c create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_trace.c create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_utils.c create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_whitelist.c create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/syscfg.yml rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{host/src/ble_hs_pvcy_priv.h => nimble/drivers/nrf51/include/ble/xcvr.h} (55%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/pkg.yml create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/src/ble_hw.c create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/src/ble_phy.c create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/include/ble/xcvr.h create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/pkg.yml create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_hw.c create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_phy.c create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_phy_trace.c create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/syscfg.yml rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/include}/host/ble_att.h (99%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/include}/host/ble_eddystone.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/include}/host/ble_gap.h (98%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/include}/host/ble_gatt.h (99%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/include}/host/ble_hs.h (96%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/include}/host/ble_hs_adv.h (99%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/include}/host/ble_hs_hci.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/include}/host/ble_hs_id.h (99%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/include}/host/ble_hs_log.h (92%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/include}/host/ble_hs_mbuf.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/include}/host/ble_hs_pvcy.h (99%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/include}/host/ble_hs_stop.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/include}/host/ble_ibeacon.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/include}/host/ble_l2cap.h (99%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/include}/host/ble_monitor.h (95%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/include}/host/ble_sm.h (98%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/include}/host/ble_store.h (99%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/include}/host/ble_uuid.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/mesh/include}/mesh/access.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/mesh/include}/mesh/cfg_cli.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/mesh/include}/mesh/cfg_srv.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/mesh/include}/mesh/glue.h (95%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/mesh/include}/mesh/health_cli.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/mesh/include}/mesh/health_srv.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/mesh/include}/mesh/main.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/mesh/include}/mesh/mesh.h (78%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/mesh/include}/mesh/model_cli.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/mesh/include}/mesh/model_srv.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/mesh/include}/mesh/porting.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/mesh/include}/mesh/proxy.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/mesh/include}/mesh/slist.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/mesh/include}/mesh/testing.h (100%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/pkg.yml rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/access.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/access.h (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/adv.c (94%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/adv.h (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/atomic.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/beacon.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/beacon.h (89%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/cfg_cli.c (99%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/cfg_srv.c (99%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/crypto.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/crypto.h (99%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/foundation.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/friend.c (99%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/friend.h (97%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/glue.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/health_cli.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/health_srv.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/light_model.c (87%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/light_model.h (87%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/lpn.c (99%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/lpn.h (97%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/mesh.c (96%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/mesh_priv.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/model_cli.c (97%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/model_srv.c (97%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/net.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/net.h (99%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/nodes.c (96%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/nodes.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/prov.c (99%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/prov.h (85%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/proxy.c (99%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/proxy.h (97%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/settings.c (99%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/settings.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/shell.c (99%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/shell.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/transport.c (99%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/mesh/src/transport.h (96%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/syscfg.yml create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pkg.yml create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/README.txt create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-gap.txt create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-gatt.txt create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-l2cap.txt create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-sm.txt create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/tpg/94654-20170317-085122560.tpg create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/tpg/94654-20170317-085441153.pts rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/services/ans/include}/services/ans/ble_svc_ans.h (100%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ans/pkg.yml rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/services/ans/src/ble_svc_ans.c (98%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ans/syscfg.yml rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/services/bas/include}/services/bas/ble_svc_bas.h (100%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/pkg.yml rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/services/bas/src/ble_svc_bas.c (92%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/syscfg.yml create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/include/services/dis/ble_svc_dis.h create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/pkg.yml create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/src/ble_svc_dis.c create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/syscfg.yml rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/services/gap/include}/services/gap/ble_svc_gap.h (100%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/pkg.yml rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/services/gap/src/ble_svc_gap.c (97%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/syscfg.yml rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/services/gatt/include}/services/gatt/ble_svc_gatt.h (100%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gatt/pkg.yml rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/services/gatt/src/ble_svc_gatt.c (95%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gatt/syscfg.yml rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/services/ias/include}/services/ias/ble_svc_ias.h (100%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ias/pkg.yml rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/services/ias/src/ble_svc_ias.c (96%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ias/syscfg.yml rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/services/ipss/include}/services/ipss/ble_svc_ipss.h (100%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ipss/pkg.yml rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/services/ipss/src/ble_svc_ipss.c (89%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ipss/syscfg.yml rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/services/lls/include}/services/lls/ble_svc_lls.h (100%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/lls/pkg.yml rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/services/lls/src/ble_svc_lls.c (97%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/lls/syscfg.yml rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/services/tps/include}/services/tps/ble_svc_tps.h (100%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/tps/pkg.yml rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/services/tps/src/ble_svc_tps.c (91%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/tps/syscfg.yml rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_att.c (100%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_att_clt.c (99%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_att_cmd.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{host/mesh/src => nimble/host}/src/ble_att_cmd_priv.h (99%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_att_priv.h (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_att_svr.c (99%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_eddystone.c (97%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_gap.c (99%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{host/mesh/src => nimble/host}/src/ble_gap_priv.h (97%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{host/mesh => nimble/host}/src/ble_gatt_priv.h (97%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_gattc.c (99%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_gatts.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_gatts_lcl.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_hs.c (97%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_hs_adv.c (99%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{host/mesh/src => nimble/host}/src/ble_hs_adv_priv.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_hs_atomic.c (100%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{host/mesh/src => nimble/host}/src/ble_hs_atomic_priv.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_hs_cfg.c (92%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_hs_conn.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{host/mesh/src => nimble/host}/src/ble_hs_conn_priv.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_hs_flow.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{host/mesh/src => nimble/host}/src/ble_hs_flow_priv.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_hs_hci.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_hs_hci_cmd.c (79%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_hs_hci_evt.c (99%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{host/services/tps => nimble/host}/src/ble_hs_hci_priv.h (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_hs_hci_util.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_hs_id.c (99%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{host/mesh/src => nimble/host}/src/ble_hs_id_priv.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_hs_log.c (92%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_hs_mbuf.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{host/mesh/src => nimble/host}/src/ble_hs_mbuf_priv.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_hs_misc.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_hs_mqueue.c (100%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_hs_periodic_sync.c (95%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{host/mesh/src => nimble/host}/src/ble_hs_periodic_sync_priv.h (97%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{host/mesh/src => nimble/host}/src/ble_hs_priv.h (95%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_hs_pvcy.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{host/mesh/src => nimble/host}/src/ble_hs_pvcy_priv.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_hs_resolv.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{host/mesh/src => nimble/host}/src/ble_hs_resolv_priv.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_hs_shutdown.c (97%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_hs_startup.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{host/mesh/src => nimble/host}/src/ble_hs_startup_priv.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_hs_stop.c (97%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_ibeacon.c (97%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_l2cap.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_l2cap_coc.c (99%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_l2cap_coc_priv.h (93%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_l2cap_priv.h (95%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_l2cap_sig.c (99%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_l2cap_sig_cmd.c (100%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_l2cap_sig_priv.h (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_monitor.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{host/mesh/src => nimble/host}/src/ble_monitor_priv.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_sm.c (99%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_sm_alg.c (97%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_sm_cmd.c (92%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_sm_lgcy.c (97%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_sm_priv.h (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_sm_sc.c (99%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_store.c (99%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_store_util.c (99%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/src/ble_uuid.c (97%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{host/mesh/src => nimble/host}/src/ble_uuid_priv.h (96%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/store/config/include}/store/config/ble_store_config.h (100%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/pkg.yml rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/store/config/src/ble_store_config.c (98%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/src/ble_store_config_conf.c rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/store/config/src/ble_store_config_priv.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/store/config/src/ble_store_nvs.c (98%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/syscfg.yml create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/syscfg.yml create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/tools/log2smtest.rb rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/nimble/host/util/include}/host/util/util.h (100%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/pkg.yml rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble}/host/util/src/addr.c (94%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/syscfg.yml rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble/include/nimble}/ble.h (98%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble/include/nimble}/ble_hci_trans.h (99%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble/include/nimble}/hci_common.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble/include/nimble}/nimble_npl.h (97%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble/include/nimble}/nimble_opt.h (96%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => nimble/include/nimble}/nimble_opt_auto.h (98%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/pkg.yml create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/syscfg.yml create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/pkg.yml rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{host/src/ble_hs_flow_priv.h => nimble/transport/ram/include/transport/ram/ble_hci_ram.h} (80%) create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/pkg.yml create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/src/ble_hci_ram.c create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/syscfg.yml create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/syscfg.yml rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/porting/nimble/include}/hal/hal_timer.h (99%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/porting/nimble/include}/log/log.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/porting/nimble/include}/log_common/ignore.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/porting/nimble/include}/log_common/log_common.h (84%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/porting/nimble/include}/logcfg/logcfg.h (99%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/porting/nimble/include}/mem/mem.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/porting/nimble/include}/modlog/modlog.h (79%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => porting/nimble/include/nimble}/nimble_port.h (88%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/porting/nimble/include}/os/endian.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/porting/nimble/include}/os/os.h (89%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/porting/nimble/include}/os/os_cputime.h (98%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/porting/nimble/include}/os/os_error.h (98%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/porting/nimble/include}/os/os_mbuf.h (99%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/porting/nimble/include}/os/os_mempool.h (99%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/porting/nimble/include}/os/os_trace_api.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/porting/nimble/include}/os/queue.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/porting/nimble/include}/os/util.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/porting/nimble/include}/stats/stats.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/porting/nimble/include}/syscfg/syscfg.h (99%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/porting/nimble/include}/sysflash/sysflash.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble/porting/nimble/include}/sysinit/sysinit.h (100%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/porting/nimble/src/endian.c (99%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/porting/nimble/src/hal_timer.c (99%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/porting/nimble/src/mem.c (96%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/porting/nimble/src/nimble_port.c (90%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/porting/nimble/src/os_cputime.c (96%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/porting/nimble/src/os_cputime_pwr2.c (98%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/porting/nimble/src/os_mbuf.c (99%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/porting/nimble/src/os_mempool.c (99%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/porting/nimble/src/os_msys_init.c (90%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => porting/npl/freertos/include/nimble}/nimble_npl_os.h (89%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => porting/npl/freertos/include/nimble}/nimble_port_freertos.h (85%) rename lib/libesp32_div/NimBLE-Arduino/src/nimble/{ => porting/npl/freertos/include/nimble}/npl_freertos.h (91%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/porting/npl/freertos/src/nimble_port_freertos.c (61%) rename lib/libesp32_div/NimBLE-Arduino/src/{ => nimble}/porting/npl/freertos/src/npl_os_freertos.c (66%) delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/src/ble_hs_hci_priv.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/src/ble_sm_priv.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/store/ram/ble_store_ram.h delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/AUTHORS delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/LICENSE delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/README delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/VERSION delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/documentation/tinycrypt.rst diff --git a/lib/libesp32_div/NimBLE-Arduino/CHANGELOG.md b/lib/libesp32_div/NimBLE-Arduino/CHANGELOG.md index 69bb956d7..b833a03dc 100644 --- a/lib/libesp32_div/NimBLE-Arduino/CHANGELOG.md +++ b/lib/libesp32_div/NimBLE-Arduino/CHANGELOG.md @@ -2,6 +2,19 @@ All notable changes to this project will be documented in this file. +## [1.3.3] - 2021-11-24 + +### Fixed +- Workaround added for FreeRTOS bug that affected timers, causing scan and advertising timer expirations to not correctly trigger callbacks. + +## [1.3.2] - 2021-11-20 + +### Fixed +- Added missing macros for scan filter. + +### Added +- `NimBLEClient::getLastError` : Gets the error code of the last function call that produces a return code from the stack. + ## [1.3.1] - 2021-08-04 ### Fixed diff --git a/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Secure_Client/NimBLE_Secure_Client.ino b/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Secure_Client/NimBLE_Secure_Client.ino index 6f9af4f74..3a35ebeb2 100644 --- a/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Secure_Client/NimBLE_Secure_Client.ino +++ b/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Secure_Client/NimBLE_Secure_Client.ino @@ -1,91 +1,91 @@ -/** NimBLE_Secure_Client Demo: - * - * This example demonstrates the secure passkey protected conenction and communication between an esp32 server and an esp32 client. - * Please note that esp32 stores auth info in nvs memory. After a successful connection it is possible that a passkey change will be ineffective. - * To avoid this clear the memory of the esp32's between security testings. esptool.py is capable of this, example: esptool.py --port /dev/ttyUSB0 erase_flash. - * - * Created: on Jan 08 2021 - * Author: mblasee - */ - -#include - -class ClientCallbacks : public NimBLEClientCallbacks -{ - uint32_t onPassKeyRequest() - { - Serial.println("Client Passkey Request"); - /** return the passkey to send to the server */ - /** Change this to be different from NimBLE_Secure_Server if you want to test what happens on key mismatch */ - return 123456; - }; -}; -static ClientCallbacks clientCB; - -void setup() -{ - Serial.begin(115200); - Serial.println("Starting NimBLE Client"); - - NimBLEDevice::init(""); - NimBLEDevice::setPower(ESP_PWR_LVL_P9); - NimBLEDevice::setSecurityAuth(true, true, true); - NimBLEDevice::setSecurityIOCap(BLE_HS_IO_KEYBOARD_ONLY); - NimBLEScan *pScan = NimBLEDevice::getScan(); - NimBLEScanResults results = pScan->start(5); - - NimBLEUUID serviceUuid("ABCD"); - - for (int i = 0; i < results.getCount(); i++) - { - NimBLEAdvertisedDevice device = results.getDevice(i); - Serial.println(device.getName().c_str()); - - if (device.isAdvertisingService(serviceUuid)) - { - NimBLEClient *pClient = NimBLEDevice::createClient(); - pClient->setClientCallbacks(&clientCB, false); - - if (pClient->connect(&device)) - { - pClient->secureConnection(); - NimBLERemoteService *pService = pClient->getService(serviceUuid); - if (pService != nullptr) - { - NimBLERemoteCharacteristic *pNonSecureCharacteristic = pService->getCharacteristic("1234"); - - if (pNonSecureCharacteristic != nullptr) - { - // Testing to read a non secured characteristic, you should be able to read this even if you have mismatching passkeys. - std::string value = pNonSecureCharacteristic->readValue(); - // print or do whatever you need with the value - Serial.println(value.c_str()); - } - - NimBLERemoteCharacteristic *pSecureCharacteristic = pService->getCharacteristic("1235"); - - if (pSecureCharacteristic != nullptr) - { - // Testing to read a secured characteristic, you should be able to read this only if you have matching passkeys, otherwise you should - // get an error like this. E NimBLERemoteCharacteristic: "<< readValue rc=261" - // This means you are trying to do something without the proper permissions. - std::string value = pSecureCharacteristic->readValue(); - // print or do whatever you need with the value - Serial.println(value.c_str()); - } - } - } - else - { - // failed to connect - Serial.println("failed to connect"); - } - - NimBLEDevice::deleteClient(pClient); - } - } -} - -void loop() -{ -} +/** NimBLE_Secure_Client Demo: + * + * This example demonstrates the secure passkey protected conenction and communication between an esp32 server and an esp32 client. + * Please note that esp32 stores auth info in nvs memory. After a successful connection it is possible that a passkey change will be ineffective. + * To avoid this clear the memory of the esp32's between security testings. esptool.py is capable of this, example: esptool.py --port /dev/ttyUSB0 erase_flash. + * + * Created: on Jan 08 2021 + * Author: mblasee + */ + +#include + +class ClientCallbacks : public NimBLEClientCallbacks +{ + uint32_t onPassKeyRequest() + { + Serial.println("Client Passkey Request"); + /** return the passkey to send to the server */ + /** Change this to be different from NimBLE_Secure_Server if you want to test what happens on key mismatch */ + return 123456; + }; +}; +static ClientCallbacks clientCB; + +void setup() +{ + Serial.begin(115200); + Serial.println("Starting NimBLE Client"); + + NimBLEDevice::init(""); + NimBLEDevice::setPower(ESP_PWR_LVL_P9); + NimBLEDevice::setSecurityAuth(true, true, true); + NimBLEDevice::setSecurityIOCap(BLE_HS_IO_KEYBOARD_ONLY); + NimBLEScan *pScan = NimBLEDevice::getScan(); + NimBLEScanResults results = pScan->start(5); + + NimBLEUUID serviceUuid("ABCD"); + + for (int i = 0; i < results.getCount(); i++) + { + NimBLEAdvertisedDevice device = results.getDevice(i); + Serial.println(device.getName().c_str()); + + if (device.isAdvertisingService(serviceUuid)) + { + NimBLEClient *pClient = NimBLEDevice::createClient(); + pClient->setClientCallbacks(&clientCB, false); + + if (pClient->connect(&device)) + { + pClient->secureConnection(); + NimBLERemoteService *pService = pClient->getService(serviceUuid); + if (pService != nullptr) + { + NimBLERemoteCharacteristic *pNonSecureCharacteristic = pService->getCharacteristic("1234"); + + if (pNonSecureCharacteristic != nullptr) + { + // Testing to read a non secured characteristic, you should be able to read this even if you have mismatching passkeys. + std::string value = pNonSecureCharacteristic->readValue(); + // print or do whatever you need with the value + Serial.println(value.c_str()); + } + + NimBLERemoteCharacteristic *pSecureCharacteristic = pService->getCharacteristic("1235"); + + if (pSecureCharacteristic != nullptr) + { + // Testing to read a secured characteristic, you should be able to read this only if you have matching passkeys, otherwise you should + // get an error like this. E NimBLERemoteCharacteristic: "<< readValue rc=261" + // This means you are trying to do something without the proper permissions. + std::string value = pSecureCharacteristic->readValue(); + // print or do whatever you need with the value + Serial.println(value.c_str()); + } + } + } + else + { + // failed to connect + Serial.println("failed to connect"); + } + + NimBLEDevice::deleteClient(pClient); + } + } +} + +void loop() +{ +} diff --git a/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Secure_Server/NimBLE_Secure_Server.ino b/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Secure_Server/NimBLE_Secure_Server.ino index f63cbc162..4de731e9f 100644 --- a/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Secure_Server/NimBLE_Secure_Server.ino +++ b/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Secure_Server/NimBLE_Secure_Server.ino @@ -1,37 +1,37 @@ -/** NimBLE_Secure_Server Demo: - * - * This example demonstrates the secure passkey protected conenction and communication between an esp32 server and an esp32 client. - * Please note that esp32 stores auth info in nvs memory. After a successful connection it is possible that a passkey change will be ineffective. - * To avoid this clear the memory of the esp32's between security testings. esptool.py is capable of this, example: esptool.py --port /dev/ttyUSB0 erase_flash. - * - * Created: on Jan 08 2021 - * Author: mblasee - */ - -#include - -void setup() { - Serial.begin(115200); - Serial.println("Starting NimBLE Server"); - NimBLEDevice::init("NimBLE"); - NimBLEDevice::setPower(ESP_PWR_LVL_P9); - - NimBLEDevice::setSecurityAuth(true, true, true); - NimBLEDevice::setSecurityPasskey(123456); - NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_ONLY); - NimBLEServer *pServer = NimBLEDevice::createServer(); - NimBLEService *pService = pServer->createService("ABCD"); - NimBLECharacteristic *pNonSecureCharacteristic = pService->createCharacteristic("1234", NIMBLE_PROPERTY::READ ); - NimBLECharacteristic *pSecureCharacteristic = pService->createCharacteristic("1235", NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::READ_AUTHEN); - - pService->start(); - pNonSecureCharacteristic->setValue("Hello Non Secure BLE"); - pSecureCharacteristic->setValue("Hello Secure BLE"); - - NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising(); - pAdvertising->addServiceUUID("ABCD"); - pAdvertising->start(); -} - -void loop() { -} +/** NimBLE_Secure_Server Demo: + * + * This example demonstrates the secure passkey protected conenction and communication between an esp32 server and an esp32 client. + * Please note that esp32 stores auth info in nvs memory. After a successful connection it is possible that a passkey change will be ineffective. + * To avoid this clear the memory of the esp32's between security testings. esptool.py is capable of this, example: esptool.py --port /dev/ttyUSB0 erase_flash. + * + * Created: on Jan 08 2021 + * Author: mblasee + */ + +#include + +void setup() { + Serial.begin(115200); + Serial.println("Starting NimBLE Server"); + NimBLEDevice::init("NimBLE"); + NimBLEDevice::setPower(ESP_PWR_LVL_P9); + + NimBLEDevice::setSecurityAuth(true, true, true); + NimBLEDevice::setSecurityPasskey(123456); + NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_ONLY); + NimBLEServer *pServer = NimBLEDevice::createServer(); + NimBLEService *pService = pServer->createService("ABCD"); + NimBLECharacteristic *pNonSecureCharacteristic = pService->createCharacteristic("1234", NIMBLE_PROPERTY::READ ); + NimBLECharacteristic *pSecureCharacteristic = pService->createCharacteristic("1235", NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::READ_AUTHEN); + + pService->start(); + pNonSecureCharacteristic->setValue("Hello Non Secure BLE"); + pSecureCharacteristic->setValue("Hello Secure BLE"); + + NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising(); + pAdvertising->addServiceUUID("ABCD"); + pAdvertising->start(); +} + +void loop() { +} diff --git a/lib/libesp32_div/NimBLE-Arduino/library.json b/lib/libesp32_div/NimBLE-Arduino/library.json index 29cff4dff..fd9dd44cf 100644 --- a/lib/libesp32_div/NimBLE-Arduino/library.json +++ b/lib/libesp32_div/NimBLE-Arduino/library.json @@ -2,7 +2,7 @@ "name": "NimBLE-Arduino", "keywords": "esp32, bluetooth", "description": "Bluetooth low energy (BLE) library for arduino-esp32 based on NimBLE", - "version": "1.3.1", + "version": "1.3.3", "frameworks": "arduino", "platforms": "espressif32" } diff --git a/lib/libesp32_div/NimBLE-Arduino/library.properties b/lib/libesp32_div/NimBLE-Arduino/library.properties index b08519454..11abace65 100644 --- a/lib/libesp32_div/NimBLE-Arduino/library.properties +++ b/lib/libesp32_div/NimBLE-Arduino/library.properties @@ -1,5 +1,5 @@ name=NimBLE-Arduino -version=1.3.1 +version=1.3.3 author=h2zero maintainer=h2zero sentence=Bluetooth low energy (BLE) library for arduino-esp32 based on NimBLE. diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLE2904.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLE2904.cpp index 80318b5b8..282eff55f 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLE2904.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLE2904.cpp @@ -16,11 +16,8 @@ * See also: * https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.characteristic_presentation_format.xml */ -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) - #include "nimconfig.h" -#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #include "NimBLE2904.h" @@ -86,5 +83,4 @@ void NimBLE2904::setUnit(uint16_t unit) { setValue((uint8_t*) &m_data, sizeof(m_data)); } // setUnit -#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) -#endif +#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLE2904.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLE2904.h index d8800dd2f..29dde51e8 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLE2904.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLE2904.h @@ -14,11 +14,8 @@ #ifndef MAIN_NIMBLE2904_H_ #define MAIN_NIMBLE2904_H_ -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) - #include "nimconfig.h" -#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #include "NimBLEDescriptor.h" @@ -82,6 +79,5 @@ private: BLE2904_Data m_data; }; // BLE2904 -#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) -#endif /* CONFIG_BT_ENABLED */ +#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */ #endif /* MAIN_NIMBLE2904_H_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAddress.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAddress.cpp index e1d3e548b..b8df5ac83 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAddress.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAddress.cpp @@ -11,7 +11,7 @@ * Created on: Jul 2, 2017 * Author: kolban */ -#include "sdkconfig.h" +#include "nimconfig.h" #if defined(CONFIG_BT_ENABLED) #include diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAddress.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAddress.h index 50f9231fe..a6e10a09c 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAddress.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAddress.h @@ -14,10 +14,15 @@ #ifndef COMPONENTS_NIMBLEADDRESS_H_ #define COMPONENTS_NIMBLEADDRESS_H_ -#include "sdkconfig.h" +#include "nimconfig.h" #if defined(CONFIG_BT_ENABLED) +#if defined(CONFIG_NIMBLE_CPP_IDF) #include "nimble/ble.h" +#else +#include "nimble/nimble/include/nimble/ble.h" +#endif + /**** FIX COMPILATION ****/ #undef min #undef max diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.cpp index ecfd49814..01dd75d41 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.cpp @@ -11,11 +11,9 @@ * Created on: Jul 3, 2017 * Author: kolban */ -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) +#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) #include "NimBLEDevice.h" #include "NimBLEAdvertisedDevice.h" @@ -783,7 +781,5 @@ size_t NimBLEAdvertisedDevice::getPayloadLength() { return m_payload.size(); } // getPayloadLength - -#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) -#endif /* CONFIG_BT_ENABLED */ +#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.h index 7d378ed0f..39410e665 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.h @@ -14,20 +14,22 @@ #ifndef COMPONENTS_NIMBLEADVERTISEDDEVICE_H_ #define COMPONENTS_NIMBLEADVERTISEDDEVICE_H_ -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) - #include "nimconfig.h" -#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) +#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) #include "NimBLEAddress.h" #include "NimBLEScan.h" #include "NimBLEUUID.h" +#if defined(CONFIG_NIMBLE_CPP_IDF) #include "host/ble_hs_adv.h" +#else +#include "nimble/nimble/host/include/host/ble_hs_adv.h" +#endif #include #include +#include class NimBLEScan; @@ -171,6 +173,5 @@ public: virtual void onResult(NimBLEAdvertisedDevice* advertisedDevice) = 0; }; -#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) -#endif /* CONFIG_BT_ENABLED */ +#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_OBSERVER */ #endif /* COMPONENTS_NIMBLEADVERTISEDDEVICE_H_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.cpp index 3112efff0..a804130f8 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.cpp @@ -13,13 +13,14 @@ * Author: kolban * */ -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) - #include "nimconfig.h" -#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) +#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) +#if defined(CONFIG_NIMBLE_CPP_IDF) #include "services/gap/ble_svc_gap.h" +#else +#include "nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h" +#endif #include "NimBLEAdvertising.h" #include "NimBLEDevice.h" #include "NimBLEServer.h" @@ -68,6 +69,7 @@ void NimBLEAdvertising::reset() { m_advDataSet = false; // Set this to non-zero to prevent auto start if host reset before started by app. m_duration = BLE_HS_FOREVER; + m_advCompCB = nullptr; } // reset @@ -653,12 +655,8 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv break; } - if(rc != 0) { - return false; - } - NIMBLE_LOGD(LOG_TAG, "<< Advertising start"); - return true; + return (rc == 0); } // start @@ -1028,5 +1026,4 @@ std::string NimBLEAdvertisementData::getPayload() { return m_payload; } // getPayload -#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) -#endif /* CONFIG_BT_ENABLED */ +#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.h index 17a866561..63a21d846 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.h @@ -14,13 +14,15 @@ #ifndef MAIN_BLEADVERTISING_H_ #define MAIN_BLEADVERTISING_H_ -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) - #include "nimconfig.h" -#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) +#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) +#if defined(CONFIG_NIMBLE_CPP_IDF) #include "host/ble_gap.h" +#else +#include "nimble/nimble/host/include/host/ble_gap.h" +#endif + /**** FIX COMPILATION ****/ #undef min #undef max @@ -132,6 +134,5 @@ private: std::vector m_uri; }; -#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) -#endif /* CONFIG_BT_ENABLED */ +#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER */ #endif /* MAIN_BLEADVERTISING_H_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEBeacon.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEBeacon.cpp index 8c4574bc2..996893ab1 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEBeacon.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEBeacon.cpp @@ -11,7 +11,7 @@ * Created on: Jan 4, 2018 * Author: kolban */ -#include "sdkconfig.h" +#include "nimconfig.h" #if defined(CONFIG_BT_ENABLED) #include diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLECharacteristic.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLECharacteristic.cpp index f3965a4dc..cc87483b7 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLECharacteristic.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLECharacteristic.cpp @@ -9,11 +9,9 @@ * Created on: Jun 22, 2017 * Author: kolban */ -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #include "NimBLECharacteristic.h" #include "NimBLE2904.h" @@ -51,7 +49,6 @@ NimBLECharacteristic::NimBLECharacteristic(const NimBLEUUID &uuid, uint16_t prop m_pCallbacks = &defaultCallback; m_pService = pService; m_value = ""; - m_valMux = portMUX_INITIALIZER_UNLOCKED; m_timestamp = 0; m_removed = 0; } // NimBLECharacteristic @@ -237,12 +234,12 @@ NimBLEUUID NimBLECharacteristic::getUUID() { * @return A std::string containing the current characteristic value. */ std::string NimBLECharacteristic::getValue(time_t *timestamp) { - portENTER_CRITICAL(&m_valMux); + ble_npl_hw_enter_critical(); std::string retVal = m_value; if(timestamp != nullptr) { *timestamp = m_timestamp; } - portEXIT_CRITICAL(&m_valMux); + ble_npl_hw_exit_critical(0); return retVal; } // getValue @@ -253,10 +250,9 @@ std::string NimBLECharacteristic::getValue(time_t *timestamp) { * @return The length of the current characteristic data. */ size_t NimBLECharacteristic::getDataLength() { - portENTER_CRITICAL(&m_valMux); + ble_npl_hw_enter_critical(); size_t len = m_value.length(); - portEXIT_CRITICAL(&m_valMux); - + ble_npl_hw_exit_critical(0); return len; } @@ -289,11 +285,10 @@ int NimBLECharacteristic::handleGapEvent(uint16_t conn_handle, uint16_t attr_han pCharacteristic->m_pCallbacks->onRead(pCharacteristic, &desc); } - portENTER_CRITICAL(&pCharacteristic->m_valMux); + ble_npl_hw_enter_critical(); rc = os_mbuf_append(ctxt->om, (uint8_t*)pCharacteristic->m_value.data(), pCharacteristic->m_value.length()); - portEXIT_CRITICAL(&pCharacteristic->m_valMux); - + ble_npl_hw_exit_critical(0); return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; } @@ -432,7 +427,7 @@ void NimBLECharacteristic::notify(bool is_notification) { int rc = 0; for (auto &it : m_subscribedVec) { - uint16_t _mtu = getService()->getServer()->getPeerMTU(it.first); + uint16_t _mtu = getService()->getServer()->getPeerMTU(it.first) - 3; // check if connected and subscribed if(_mtu == 0 || it.second == 0) { @@ -448,8 +443,8 @@ void NimBLECharacteristic::notify(bool is_notification) { } } - if (length > _mtu - 3) { - NIMBLE_LOGW(LOG_TAG, "- Truncating to %d bytes (maximum notify size)", _mtu - 3); + if (length > _mtu) { + NIMBLE_LOGW(LOG_TAG, "- Truncating to %d bytes (maximum notify size)", _mtu); } if(is_notification && (!(it.second & NIMBLE_SUB_NOTIFY))) { @@ -528,10 +523,10 @@ void NimBLECharacteristic::setValue(const uint8_t* data, size_t length) { } time_t t = time(nullptr); - portENTER_CRITICAL(&m_valMux); + ble_npl_hw_enter_critical(); m_value = std::string((char*)data, length); m_timestamp = t; - portEXIT_CRITICAL(&m_valMux); + ble_npl_hw_exit_critical(0); NIMBLE_LOGD(LOG_TAG, "<< setValue"); } // setValue @@ -641,6 +636,4 @@ void NimBLECharacteristicCallbacks::onSubscribe(NimBLECharacteristic* pCharacter NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onSubscribe: default"); } - -#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) -#endif /* CONFIG_BT_ENABLED */ +#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLECharacteristic.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLECharacteristic.h index 6008d127f..9edfb54b3 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLECharacteristic.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLECharacteristic.h @@ -13,13 +13,15 @@ #ifndef MAIN_NIMBLECHARACTERISTIC_H_ #define MAIN_NIMBLECHARACTERISTIC_H_ -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) - #include "nimconfig.h" -#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#if defined(CONFIG_NIMBLE_CPP_IDF) #include "host/ble_hs.h" +#else +#include "nimble/nimble/host/include/host/ble_hs.h" +#endif + /**** FIX COMPILATION ****/ #undef min #undef max @@ -151,7 +153,6 @@ private: NimBLEService* m_pService; std::string m_value; std::vector m_dscVec; - portMUX_TYPE m_valMux; time_t m_timestamp; uint8_t m_removed; @@ -195,6 +196,5 @@ public: virtual void onSubscribe(NimBLECharacteristic* pCharacteristic, ble_gap_conn_desc* desc, uint16_t subValue); }; -#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) -#endif /* CONFIG_BT_ENABLED */ +#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */ #endif /*MAIN_NIMBLECHARACTERISTIC_H_*/ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEClient.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEClient.cpp index a171b8cc0..9f4e08fdb 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEClient.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEClient.cpp @@ -11,11 +11,8 @@ * Author: kolban */ -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) - #include "nimconfig.h" -#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) #include "NimBLEClient.h" #include "NimBLEDevice.h" @@ -24,8 +21,11 @@ #include #include +#if defined(CONFIG_NIMBLE_CPP_IDF) #include "nimble/nimble_port.h" - +#else +#include "nimble/porting/nimble/include/nimble/nimble_port.h" +#endif static const char* LOG_TAG = "NimBLEClient"; static NimBLEClientCallbacks defaultCallbacks; @@ -63,6 +63,7 @@ NimBLEClient::NimBLEClient(const NimBLEAddress &peerAddress) : m_peerAddress(pee m_deleteCallbacks = false; m_pTaskData = nullptr; m_connEstablished = false; + m_lastErr = 0; m_pConnParams.scan_itvl = 16; // Scan interval in 0.625ms units (NimBLE Default) m_pConnParams.scan_window = 16; // Scan window in 0.625ms units (NimBLE Default) @@ -73,6 +74,7 @@ NimBLEClient::NimBLEClient(const NimBLEAddress &peerAddress) : m_peerAddress(pee m_pConnParams.min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN; // Minimum length of connection event in 0.625ms units m_pConnParams.max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN; // Maximum length of connection event in 0.625ms units + memset(&m_dcTimer, 0, sizeof(m_dcTimer)); ble_npl_callout_init(&m_dcTimer, nimble_port_get_dflt_eventq(), NimBLEClient::dcTimerCb, this); } // NimBLEClient @@ -251,6 +253,8 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) { } while (rc == BLE_HS_EBUSY); + m_lastErr = rc; + if(rc != 0) { m_pTaskData = nullptr; return false; @@ -273,6 +277,7 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) { return false; } else if(taskData.rc != 0){ + m_lastErr = taskData.rc; NIMBLE_LOGE(LOG_TAG, "Connection failed; status=%d %s", taskData.rc, NimBLEUtils::returnCodeToString(taskData.rc)); @@ -314,6 +319,7 @@ bool NimBLEClient::secureConnection() { int rc = NimBLEDevice::startSecurity(m_conn_id); if(rc != 0){ + m_lastErr = rc; m_pTaskData = nullptr; return false; } @@ -322,6 +328,7 @@ bool NimBLEClient::secureConnection() { } while (taskData.rc == (BLE_HS_ERR_HCI_BASE + BLE_ERR_PINKEY_MISSING) && retryCount--); if(taskData.rc != 0){ + m_lastErr = taskData.rc; return false; } @@ -372,6 +379,7 @@ int NimBLEClient::disconnect(uint8_t reason) { } NIMBLE_LOGD(LOG_TAG, "<< disconnect()"); + m_lastErr = rc; return rc; } // disconnect @@ -436,6 +444,28 @@ void NimBLEClient::updateConnParams(uint16_t minInterval, uint16_t maxInterval, } // updateConnParams +/** + * @brief Request an update of the data packet length. + * * Can only be used after a connection has been established. + * @details Sends a data length update request to the server the client is connected to. + * The Data Length Extension (DLE) allows to increase the Data Channel Payload from 27 bytes to up to 251 bytes. + * The server needs to support the Bluetooth 4.2 specifications, to be capable of DLE. + * @param [in] tx_octets The preferred number of payload octets to use (Range 0x001B-0x00FB). + */ +void NimBLEClient::setDataLen(uint16_t tx_octets) { +#ifdef CONFIG_NIMBLE_CPP_IDF // not yet available in IDF, Sept 9 2021 + return; +#else + uint16_t tx_time = (tx_octets + 14) * 8; + + int rc = ble_gap_set_data_len(m_conn_id, tx_octets, tx_time); + if(rc != 0) { + NIMBLE_LOGE(LOG_TAG, "Set data length error: %d, %s", rc, NimBLEUtils::returnCodeToString(rc)); + } +#endif +} // setDataLen + + /** * @brief Get detailed information about the current peer connection. */ @@ -512,6 +542,7 @@ int NimBLEClient::getRssi() { if(rc != 0) { NIMBLE_LOGE(LOG_TAG, "Failed to read RSSI error code: %d, %s", rc, NimBLEUtils::returnCodeToString(rc)); + m_lastErr = rc; return 0; } @@ -650,11 +681,13 @@ bool NimBLEClient::retrieveServices(const NimBLEUUID *uuid_filter) { if (rc != 0) { NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_svcs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); + m_lastErr = rc; return false; } // wait until we have all the services ulTaskNotifyTake(pdTRUE, portMAX_DELAY); + m_lastErr = taskData.rc; if(taskData.rc == 0){ NIMBLE_LOGD(LOG_TAG, "<< retrieveServices"); @@ -925,11 +958,11 @@ uint16_t NimBLEClient::getMTU() { (*characteristic)->toString().c_str()); time_t t = time(nullptr); - portENTER_CRITICAL(&(*characteristic)->m_valMux); + ble_npl_hw_enter_critical(); (*characteristic)->m_value = std::string((char *)event->notify_rx.om->om_data, event->notify_rx.om->om_len); (*characteristic)->m_timestamp = t; - portEXIT_CRITICAL(&(*characteristic)->m_valMux); + ble_npl_hw_exit_critical(0); if ((*characteristic)->m_notifyCallback != nullptr) { NIMBLE_LOGD(LOG_TAG, "Invoking callback for notification on characteristic %s", @@ -1136,6 +1169,15 @@ std::string NimBLEClient::toString() { } // toString +/** + * @brief Get the last error code reported by the NimBLE host + * @return int, the NimBLE error code. + */ +int NimBLEClient::getLastError() { + return m_lastErr; +} // getLastError + + void NimBLEClientCallbacks::onConnect(NimBLEClient* pClient) { NIMBLE_LOGD("NimBLEClientCallbacks", "onConnect: default"); } @@ -1170,5 +1212,4 @@ bool NimBLEClientCallbacks::onConfirmPIN(uint32_t pin){ return true; } -#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) -#endif // CONFIG_BT_ENABLED +#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEClient.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEClient.h index d90086c4a..37700b7c4 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEClient.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEClient.h @@ -14,11 +14,8 @@ #ifndef MAIN_NIMBLECLIENT_H_ #define MAIN_NIMBLECLIENT_H_ -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) - #include "nimconfig.h" -#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) #include "NimBLEAddress.h" #include "NimBLEUUID.h" @@ -71,8 +68,10 @@ public: uint16_t scanInterval=16, uint16_t scanWindow=16); void updateConnParams(uint16_t minInterval, uint16_t maxInterval, uint16_t latency, uint16_t timeout); + void setDataLen(uint16_t tx_octets); void discoverAttributes(); NimBLEConnInfo getConnInfo(); + int getLastError(); private: NimBLEClient(const NimBLEAddress &peerAddress); @@ -90,6 +89,7 @@ private: bool retrieveServices(const NimBLEUUID *uuid_filter = nullptr); NimBLEAddress m_peerAddress; + int m_lastErr; uint16_t m_conn_id; bool m_connEstablished; bool m_deleteCallbacks; @@ -158,6 +158,5 @@ public: virtual bool onConfirmPIN(uint32_t pin); }; -#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) -#endif // CONFIG_BT_ENABLED +#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */ #endif /* MAIN_NIMBLECLIENT_H_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDescriptor.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDescriptor.cpp index f94676607..5b0db1a64 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDescriptor.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDescriptor.cpp @@ -11,11 +11,9 @@ * Created on: Jun 22, 2017 * Author: kolban */ -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #include "NimBLEService.h" #include "NimBLEDescriptor.h" @@ -51,7 +49,6 @@ NimBLEDescriptor::NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties, uint16_ m_pCharacteristic = pCharacteristic; m_pCallbacks = &defaultCallbacks; // No initial callback. m_value.attr_value = (uint8_t*) calloc(max_len,1); // Allocate storage for the value. - m_valMux = portMUX_INITIALIZER_UNLOCKED; m_properties = 0; m_removed = 0; @@ -145,6 +142,9 @@ NimBLECharacteristic* NimBLEDescriptor::getCharacteristic() { int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { + (void)conn_handle; + (void)attr_handle; + const ble_uuid_t *uuid; int rc; NimBLEDescriptor* pDescriptor = (NimBLEDescriptor*)arg; @@ -161,9 +161,10 @@ int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle, if(ctxt->om->om_pkthdr_len > 8) { pDescriptor->m_pCallbacks->onRead(pDescriptor); } - portENTER_CRITICAL(&pDescriptor->m_valMux); + + ble_npl_hw_enter_critical(); rc = os_mbuf_append(ctxt->om, pDescriptor->getValue(), pDescriptor->getLength()); - portEXIT_CRITICAL(&pDescriptor->m_valMux); + ble_npl_hw_exit_critical(0); return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; } @@ -234,10 +235,12 @@ void NimBLEDescriptor::setValue(const uint8_t* data, size_t length) { NIMBLE_LOGE(LOG_TAG, "Size %d too large, must be no bigger than %d", length, m_value.attr_max_len); return; } - portENTER_CRITICAL(&m_valMux); + + ble_npl_hw_enter_critical(); m_value.attr_len = length; memcpy(m_value.attr_value, data, length); - portEXIT_CRITICAL(&m_valMux); + ble_npl_hw_exit_critical(0); + } // setValue @@ -277,6 +280,7 @@ NimBLEDescriptorCallbacks::~NimBLEDescriptorCallbacks() {} * @param [in] pDescriptor The descriptor that is the source of the event. */ void NimBLEDescriptorCallbacks::onRead(NimBLEDescriptor* pDescriptor) { + (void)pDescriptor; NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onRead: default"); } // onRead @@ -286,8 +290,8 @@ void NimBLEDescriptorCallbacks::onRead(NimBLEDescriptor* pDescriptor) { * @param [in] pDescriptor The descriptor that is the source of the event. */ void NimBLEDescriptorCallbacks::onWrite(NimBLEDescriptor* pDescriptor) { + (void)pDescriptor; NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onWrite: default"); } // onWrite -#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) -#endif /* CONFIG_BT_ENABLED */ +#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDescriptor.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDescriptor.h index 5dc0ce89b..fe6c73303 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDescriptor.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDescriptor.h @@ -14,11 +14,9 @@ #ifndef MAIN_NIMBLEDESCRIPTOR_H_ #define MAIN_NIMBLEDESCRIPTOR_H_ -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #include "NimBLECharacteristic.h" #include "NimBLEUUID.h" @@ -92,7 +90,6 @@ private: NimBLECharacteristic* m_pCharacteristic; uint8_t m_properties; attr_value_t m_value; - portMUX_TYPE m_valMux; uint8_t m_removed; }; // NimBLEDescriptor @@ -113,6 +110,5 @@ public: #include "NimBLE2904.h" -#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) -#endif /* CONFIG_BT_ENABLED */ +#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */ #endif /* MAIN_NIMBLEDESCRIPTOR_H_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.cpp index bc253659a..0302cb8a8 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.cpp @@ -11,27 +11,45 @@ * Created on: Mar 16, 2017 * Author: kolban */ -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" +#if defined(CONFIG_BT_ENABLED) + #include "NimBLEDevice.h" #include "NimBLEUtils.h" -#include "esp_err.h" -#include "esp_bt.h" -#include "nvs_flash.h" -#include "esp_nimble_hci.h" -#include "nimble/nimble_port.h" -#include "nimble/nimble_port_freertos.h" -#include "host/ble_hs.h" -#include "host/ble_hs_pvcy.h" -#include "host/util/util.h" -#include "services/gap/ble_svc_gap.h" -#include "services/gatt/ble_svc_gatt.h" +#ifdef ESP_PLATFORM +# include "esp_err.h" +# include "esp_bt.h" +# include "nvs_flash.h" +# if defined(CONFIG_NIMBLE_CPP_IDF) +# include "esp_nimble_hci.h" +# include "nimble/nimble_port.h" +# include "nimble/nimble_port_freertos.h" +# include "host/ble_hs.h" +# include "host/ble_hs_pvcy.h" +# include "host/util/util.h" +# include "services/gap/ble_svc_gap.h" +# include "services/gatt/ble_svc_gatt.h" +# else +# include "nimble/esp_port/esp-hci/include/esp_nimble_hci.h" +# endif +#else +# include "nimble/nimble/controller/include/controller/ble_phy.h" +#endif -#ifdef CONFIG_ENABLE_ARDUINO_DEPENDS -#include "esp32-hal-bt.h" +#ifndef CONFIG_NIMBLE_CPP_IDF +# include "nimble/porting/nimble/include/nimble/nimble_port.h" +# include "nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h" +# include "nimble/nimble/host/include/host/ble_hs.h" +# include "nimble/nimble/host/include/host/ble_hs_pvcy.h" +# include "nimble/nimble/host/util/include/host/util/util.h" +# include "nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h" +# include "nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h" +#endif + +#if defined(ESP_PLATFORM) && defined(CONFIG_ENABLE_ARDUINO_DEPENDS) +# include "esp32-hal-bt.h" #endif #include "NimBLELog.h" @@ -63,9 +81,10 @@ std::list NimBLEDevice::m_ignoreList; std::vector NimBLEDevice::m_whiteList; NimBLESecurityCallbacks* NimBLEDevice::m_securityCallbacks = nullptr; uint8_t NimBLEDevice::m_own_addr_type = BLE_OWN_ADDR_PUBLIC; +#ifdef ESP_PLATFORM uint16_t NimBLEDevice::m_scanDuplicateSize = CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE; uint8_t NimBLEDevice::m_scanFilterMode = CONFIG_BTDM_SCAN_DUPL_TYPE; - +#endif /** * @brief Create a new instance of a server. @@ -130,7 +149,8 @@ void NimBLEDevice::stopAdvertising() { * try and release/delete it. */ #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) -/* STATIC */ NimBLEScan* NimBLEDevice::getScan() { +/* STATIC */ +NimBLEScan* NimBLEDevice::getScan() { if (m_pScan == nullptr) { m_pScan = new NimBLEScan(); } @@ -147,7 +167,8 @@ void NimBLEDevice::stopAdvertising() { * @return A reference to the new client object. */ #if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) -/* STATIC */ NimBLEClient* NimBLEDevice::createClient(NimBLEAddress peerAddress) { +/* STATIC */ +NimBLEClient* NimBLEDevice::createClient(NimBLEAddress peerAddress) { if(m_cList.size() >= NIMBLE_MAX_CONNECTIONS) { NIMBLE_LOGW(LOG_TAG,"Number of clients exceeds Max connections. Cur=%d Max=%d", m_cList.size(), NIMBLE_MAX_CONNECTIONS); @@ -165,7 +186,8 @@ void NimBLEDevice::stopAdvertising() { * Checks if it is connected or trying to connect and disconnects/stops it first. * @param [in] pClient A pointer to the client object. */ -/* STATIC */ bool NimBLEDevice::deleteClient(NimBLEClient* pClient) { +/* STATIC */ +bool NimBLEDevice::deleteClient(NimBLEClient* pClient) { if(pClient == nullptr) { return false; } @@ -209,7 +231,8 @@ void NimBLEDevice::stopAdvertising() { * @brief Get the list of created client objects. * @return A pointer to the list of clients. */ -/* STATIC */std::list* NimBLEDevice::getClientList() { +/* STATIC */ +std::list* NimBLEDevice::getClientList() { return &m_cList; } // getClientList @@ -218,7 +241,8 @@ void NimBLEDevice::stopAdvertising() { * @brief Get the number of created client objects. * @return Number of client objects created. */ -/* STATIC */size_t NimBLEDevice::getClientListSize() { +/* STATIC */ +size_t NimBLEDevice::getClientListSize() { return m_cList.size(); } // getClientList @@ -228,7 +252,8 @@ void NimBLEDevice::stopAdvertising() { * @param [in] conn_id The client connection ID to search for. * @return A pointer to the client object with the spcified connection ID. */ -/* STATIC */NimBLEClient* NimBLEDevice::getClientByID(uint16_t conn_id) { +/* STATIC */ +NimBLEClient* NimBLEDevice::getClientByID(uint16_t conn_id) { for(auto it = m_cList.cbegin(); it != m_cList.cend(); ++it) { if((*it)->getConnId() == conn_id) { return (*it); @@ -244,7 +269,8 @@ void NimBLEDevice::stopAdvertising() { * @param [in] peer_addr The address of the peer to search for. * @return A pointer to the client object with the peer address. */ -/* STATIC */NimBLEClient* NimBLEDevice::getClientByPeerAddress(const NimBLEAddress &peer_addr) { +/* STATIC */ +NimBLEClient* NimBLEDevice::getClientByPeerAddress(const NimBLEAddress &peer_addr) { for(auto it = m_cList.cbegin(); it != m_cList.cend(); ++it) { if((*it)->getPeerAddress().equals(peer_addr)) { return (*it); @@ -258,7 +284,8 @@ void NimBLEDevice::stopAdvertising() { * @brief Finds the first disconnected client in the list. * @return A pointer to the first client object that is not connected to a peer. */ -/* STATIC */NimBLEClient* NimBLEDevice::getDisconnectedClient() { +/* STATIC */ +NimBLEClient* NimBLEDevice::getDisconnectedClient() { for(auto it = m_cList.cbegin(); it != m_cList.cend(); ++it) { if(!(*it)->isConnected()) { return (*it); @@ -269,7 +296,7 @@ void NimBLEDevice::stopAdvertising() { #endif // #if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) - +#ifdef ESP_PLATFORM /** * @brief Set the transmission power. * @param [in] powerLevel The power level to set, can be one of: @@ -295,12 +322,15 @@ void NimBLEDevice::stopAdvertising() { * * ESP_BLE_PWR_TYPE_SCAN = 10, For scan * * ESP_BLE_PWR_TYPE_DEFAULT = 11, For default, if not set other, it will use default value */ -/* STATIC */ void NimBLEDevice::setPower(esp_power_level_t powerLevel, esp_ble_power_type_t powerType) { +/* STATIC */ +void NimBLEDevice::setPower(esp_power_level_t powerLevel, esp_ble_power_type_t powerType) { NIMBLE_LOGD(LOG_TAG, ">> setPower: %d (type: %d)", powerLevel, powerType); + esp_err_t errRc = esp_ble_tx_power_set(powerType, powerLevel); if (errRc != ESP_OK) { NIMBLE_LOGE(LOG_TAG, "esp_ble_tx_power_set: rc=%d", errRc); } + NIMBLE_LOGD(LOG_TAG, "<< setPower"); } // setPower @@ -322,9 +352,8 @@ void NimBLEDevice::stopAdvertising() { * * ESP_BLE_PWR_TYPE_DEFAULT = 11, For default, if not set other, it will use default value * @return the power level currently used by the type specified. */ - -/* STATIC */ int NimBLEDevice::getPower(esp_ble_power_type_t powerType) { - +/* STATIC */ +int NimBLEDevice::getPower(esp_ble_power_type_t powerType) { switch(esp_ble_tx_power_get(powerType)) { case ESP_PWR_LVL_N12: return -12; @@ -347,13 +376,25 @@ void NimBLEDevice::stopAdvertising() { } } // getPower +#else + +void NimBLEDevice::setPower(int dbm) { + ble_phy_txpwr_set(dbm); +} + + +int NimBLEDevice::getPower() { + return ble_phy_txpwr_get(); +} +#endif /** * @brief Get our device address. * @return A NimBLEAddress object of our public address if we have one, * if not then our current random address. */ -/* STATIC*/ NimBLEAddress NimBLEDevice::getAddress() { +/* STATIC*/ +NimBLEAddress NimBLEDevice::getAddress() { ble_addr_t addr = {BLE_ADDR_PUBLIC, 0}; if(BLE_HS_ENOADDR == ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, addr.val, NULL)) { @@ -370,7 +411,8 @@ void NimBLEDevice::stopAdvertising() { * @brief Return a string representation of the address of this device. * @return A string representation of this device address. */ -/* STATIC */ std::string NimBLEDevice::toString() { +/* STATIC */ +std::string NimBLEDevice::toString() { return getAddress().toString(); } // toString @@ -380,7 +422,8 @@ void NimBLEDevice::stopAdvertising() { * @param [in] mtu Value to set local mtu: * * This should be larger than 23 and lower or equal to BLE_ATT_MTU_MAX = 527. */ -/* STATIC */int NimBLEDevice::setMTU(uint16_t mtu) { +/* STATIC */ +int NimBLEDevice::setMTU(uint16_t mtu) { NIMBLE_LOGD(LOG_TAG, ">> setLocalMTU: %d", mtu); int rc = ble_att_set_preferred_mtu(mtu); @@ -398,11 +441,13 @@ void NimBLEDevice::stopAdvertising() { * @brief Get local MTU value set. * @return The current preferred MTU setting. */ -/* STATIC */uint16_t NimBLEDevice::getMTU() { +/* STATIC */ +uint16_t NimBLEDevice::getMTU() { return ble_att_preferred_mtu(); } +#ifdef ESP_PLATFORM /** * @brief Set the duplicate filter cache size for filtering scanned devices. * @param [in] cacheSize The number of advertisements filtered before the cache is reset.\n @@ -448,6 +493,7 @@ void NimBLEDevice::setScanFilterMode(uint8_t mode) { m_scanFilterMode = mode; } +#endif #if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) || defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) /** @@ -470,7 +516,7 @@ int NimBLEDevice::getNumBonds() { /** * @brief Deletes all bonding information. */ - /*STATIC*/ +/*STATIC*/ void NimBLEDevice::deleteAllBonds() { ble_store_clear(); } @@ -550,6 +596,7 @@ NimBLEAddress NimBLEDevice::getBondedAddress(int index) { * @param [in] address The address to check for in the whitelist. * @returns true if the address is in the whitelist. */ +/*STATIC*/ bool NimBLEDevice::onWhiteList(const NimBLEAddress & address) { for (auto &it : m_whiteList) { if (it == address) { @@ -566,6 +613,7 @@ bool NimBLEDevice::onWhiteList(const NimBLEAddress & address) { * @param [in] address The address to add to the whitelist. * @returns true if successful. */ +/*STATIC*/ bool NimBLEDevice::whiteListAdd(const NimBLEAddress & address) { if (NimBLEDevice::onWhiteList(address)) { return true; @@ -597,6 +645,7 @@ bool NimBLEDevice::whiteListAdd(const NimBLEAddress & address) { * @param [in] address The address to remove from the whitelist. * @returns true if successful. */ +/*STATIC*/ bool NimBLEDevice::whiteListRemove(const NimBLEAddress & address) { if (!NimBLEDevice::onWhiteList(address)) { return true; @@ -636,6 +685,7 @@ bool NimBLEDevice::whiteListRemove(const NimBLEAddress & address) { * @brief Gets the count of addresses in the whitelist. * @returns The number of addresses in the whitelist. */ +/*STATIC*/ size_t NimBLEDevice::getWhiteListCount() { return m_whiteList.size(); } @@ -646,6 +696,7 @@ size_t NimBLEDevice::getWhiteListCount() { * @param [in] index The vector index to retrieve the address from. * @returns the NimBLEAddress at the whitelist index or nullptr if not found. */ +/*STATIC*/ NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) { if (index > m_whiteList.size()) { NIMBLE_LOGE(LOG_TAG, "Invalid index; %u", index); @@ -659,7 +710,8 @@ NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) { * @brief Host reset, we pass the message so we don't make calls until resynced. * @param [in] reason The reason code for the reset. */ -/* STATIC */ void NimBLEDevice::onReset(int reason) +/* STATIC */ +void NimBLEDevice::onReset(int reason) { if(!m_synced) { return; @@ -683,7 +735,8 @@ NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) { /** * @brief Host resynced with controller, all clear to make calls to the stack. */ -/* STATIC */ void NimBLEDevice::onSync(void) +/* STATIC */ +void NimBLEDevice::onSync(void) { NIMBLE_LOGI(LOG_TAG, "NimBle host synced."); // This check is needed due to potentially being called multiple times in succession @@ -696,6 +749,14 @@ NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) { int rc = ble_hs_util_ensure_addr(0); assert(rc == 0); +#ifndef ESP_PLATFORM + rc = ble_hs_id_infer_auto(m_own_addr_type, &m_own_addr_type); + if (rc != 0) { + NIMBLE_LOGE(LOG_TAG, "error determining address type; rc=%d", rc); + return; + } +#endif + // Yield for houskeeping before returning to operations. // Occasionally triggers exception without. taskYIELD(); @@ -721,9 +782,11 @@ NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) { /** * @brief The main host task. */ -/* STATIC */ void NimBLEDevice::host_task(void *param) +/* STATIC */ +void NimBLEDevice::host_task(void *param) { NIMBLE_LOGI(LOG_TAG, "BLE Host Task Started"); + /* This function will return only when nimble_port_stop() is executed */ nimble_port_run(); @@ -735,9 +798,11 @@ NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) { * @brief Initialize the %BLE environment. * @param [in] deviceName The device name of the device. */ -/* STATIC */ void NimBLEDevice::init(const std::string &deviceName) { +/* STATIC */ +void NimBLEDevice::init(const std::string &deviceName) { if(!initialized){ int rc=0; +#ifdef ESP_PLATFORM esp_err_t errRc = ESP_OK; #ifdef CONFIG_ENABLE_ARDUINO_DEPENDS @@ -769,6 +834,7 @@ NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) { ESP_ERROR_CHECK(esp_bt_controller_init(&bt_cfg)); ESP_ERROR_CHECK(esp_bt_controller_enable(ESP_BT_MODE_BLE)); ESP_ERROR_CHECK(esp_nimble_hci_init()); +#endif nimble_port_init(); // Setup callbacks for host events @@ -793,9 +859,10 @@ NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) { nimble_port_freertos_init(NimBLEDevice::host_task); } + // Wait for host and controller to sync before returning and accepting new tasks while(!m_synced){ - vTaskDelay(1 / portTICK_PERIOD_MS); + taskYIELD(); } initialized = true; // Set the initialization flag to ensure we are only initialized once. @@ -807,16 +874,17 @@ NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) { * @param [in] clearAll If true, deletes all server/advertising/scan/client objects after deinitializing. * @note If clearAll is true when called, any references to the created objects become invalid. */ -/* STATIC */ void NimBLEDevice::deinit(bool clearAll) { +/* STATIC */ +void NimBLEDevice::deinit(bool clearAll) { int ret = nimble_port_stop(); if (ret == 0) { nimble_port_deinit(); - +#ifdef ESP_PLATFORM ret = esp_nimble_hci_and_controller_deinit(); if (ret != ESP_OK) { NIMBLE_LOGE(LOG_TAG, "esp_nimble_hci_and_controller_deinit() failed with error: %d", ret); } - +#endif initialized = false; m_synced = false; @@ -863,6 +931,7 @@ NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) { * @brief Check if the initialization is complete. * @return true if initialized. */ +/*STATIC*/ bool NimBLEDevice::getInitialized() { return initialized; } // getInitialized @@ -874,7 +943,8 @@ bool NimBLEDevice::getInitialized() { * @param mitm If true we are capable of man in the middle protection, false if not. * @param sc If true we will perform secure connection pairing, false we will use legacy pairing. */ -/*STATIC*/ void NimBLEDevice::setSecurityAuth(bool bonding, bool mitm, bool sc) { +/*STATIC*/ +void NimBLEDevice::setSecurityAuth(bool bonding, bool mitm, bool sc) { NIMBLE_LOGD(LOG_TAG, "Setting bonding: %d, mitm: %d, sc: %d",bonding,mitm,sc); ble_hs_cfg.sm_bonding = bonding; ble_hs_cfg.sm_mitm = mitm; @@ -891,7 +961,8 @@ bool NimBLEDevice::getInitialized() { * * 0x08 BLE_SM_PAIR_AUTHREQ_SC * * 0x10 BLE_SM_PAIR_AUTHREQ_KEYPRESS - not yet supported. */ -/*STATIC*/void NimBLEDevice::setSecurityAuth(uint8_t auth_req) { +/*STATIC*/ +void NimBLEDevice::setSecurityAuth(uint8_t auth_req) { NimBLEDevice::setSecurityAuth((auth_req & BLE_SM_PAIR_AUTHREQ_BOND)>0, (auth_req & BLE_SM_PAIR_AUTHREQ_MITM)>0, (auth_req & BLE_SM_PAIR_AUTHREQ_SC)>0); @@ -907,7 +978,8 @@ bool NimBLEDevice::getInitialized() { * * 0x03 BLE_HS_IO_NO_INPUT_OUTPUT NoInputNoOutput IO capability * * 0x04 BLE_HS_IO_KEYBOARD_DISPLAY KeyboardDisplay Only IO capability */ -/*STATIC*/ void NimBLEDevice::setSecurityIOCap(uint8_t iocap) { +/*STATIC*/ +void NimBLEDevice::setSecurityIOCap(uint8_t iocap) { ble_hs_cfg.sm_io_cap = iocap; } // setSecurityIOCap @@ -921,7 +993,8 @@ bool NimBLEDevice::getInitialized() { * * 0x04: BLE_SM_PAIR_KEY_DIST_SIGN * * 0x08: BLE_SM_PAIR_KEY_DIST_LINK */ -/*STATIC*/void NimBLEDevice::setSecurityInitKey(uint8_t init_key) { +/*STATIC*/ +void NimBLEDevice::setSecurityInitKey(uint8_t init_key) { ble_hs_cfg.sm_our_key_dist = init_key; } // setsSecurityInitKey @@ -935,7 +1008,8 @@ bool NimBLEDevice::getInitialized() { * * 0x04: BLE_SM_PAIR_KEY_DIST_SIGN * * 0x08: BLE_SM_PAIR_KEY_DIST_LINK */ -/*STATIC*/void NimBLEDevice::setSecurityRespKey(uint8_t resp_key) { +/*STATIC*/ +void NimBLEDevice::setSecurityRespKey(uint8_t resp_key) { ble_hs_cfg.sm_their_key_dist = resp_key; } // setsSecurityRespKey @@ -944,7 +1018,8 @@ bool NimBLEDevice::getInitialized() { * @brief Set the passkey the server will ask for when pairing. * @param [in] pin The passkey to use. */ -/*STATIC*/void NimBLEDevice::setSecurityPasskey(uint32_t pin) { +/*STATIC*/ +void NimBLEDevice::setSecurityPasskey(uint32_t pin) { m_passkey = pin; } // setSecurityPasskey @@ -953,7 +1028,8 @@ bool NimBLEDevice::getInitialized() { * @brief Get the current passkey used for pairing. * @return The current passkey. */ -/*STATIC*/uint32_t NimBLEDevice::getSecurityPasskey() { +/*STATIC*/ +uint32_t NimBLEDevice::getSecurityPasskey() { return m_passkey; } // getSecurityPasskey @@ -963,11 +1039,13 @@ bool NimBLEDevice::getInitialized() { * @param [in] callbacks Pointer to NimBLESecurityCallbacks class * @deprecated For backward compatibility, New code should use client/server callback methods. */ +/*STATIC*/ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) { NimBLEDevice::m_securityCallbacks = callbacks; } // setSecurityCallbacks +#ifdef ESP_PLATFORM /** * @brief Set the own address type. * @param [in] own_addr_type Own Bluetooth Device address type.\n @@ -978,6 +1056,7 @@ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) { * * 0x03: BLE_OWN_ADDR_RPA_RANDOM_DEFAULT * @param [in] useNRPA If true, and address type is random, uses a non-resolvable random address. */ +/*STATIC*/ void NimBLEDevice::setOwnAddrType(uint8_t own_addr_type, bool useNRPA) { m_own_addr_type = own_addr_type; switch (own_addr_type) { @@ -1001,18 +1080,15 @@ void NimBLEDevice::setOwnAddrType(uint8_t own_addr_type, bool useNRPA) { break; } } // setOwnAddrType - +#endif /** * @brief Start the connection securing and authorization for this connection. * @param conn_id The connection id of the peer device. * @returns NimBLE stack return code, 0 = success. */ -/* STATIC */int NimBLEDevice::startSecurity(uint16_t conn_id) { - /* if(m_securityCallbacks != nullptr) { - m_securityCallbacks->onSecurityRequest(); - } - */ +/* STATIC */ +int NimBLEDevice::startSecurity(uint16_t conn_id) { int rc = ble_gap_security_initiate(conn_id); if(rc != 0){ NIMBLE_LOGE(LOG_TAG, "ble_gap_security_initiate: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); @@ -1027,7 +1103,8 @@ void NimBLEDevice::setOwnAddrType(uint8_t own_addr_type, bool useNRPA) { * @param [in] address The address to look for. * @return True if ignoring. */ -/*STATIC*/ bool NimBLEDevice::isIgnored(const NimBLEAddress &address) { +/*STATIC*/ +bool NimBLEDevice::isIgnored(const NimBLEAddress &address) { for(auto &it : m_ignoreList) { if(it.equals(address)){ return true; @@ -1042,7 +1119,8 @@ void NimBLEDevice::setOwnAddrType(uint8_t own_addr_type, bool useNRPA) { * @brief Add a device to the ignore list. * @param [in] address The address of the device we want to ignore. */ -/*STATIC*/ void NimBLEDevice::addIgnored(const NimBLEAddress &address) { +/*STATIC*/ +void NimBLEDevice::addIgnored(const NimBLEAddress &address) { m_ignoreList.push_back(address); } @@ -1051,7 +1129,8 @@ void NimBLEDevice::setOwnAddrType(uint8_t own_addr_type, bool useNRPA) { * @brief Remove a device from the ignore list. * @param [in] address The address of the device we want to remove from the list. */ -/*STATIC*/void NimBLEDevice::removeIgnored(const NimBLEAddress &address) { +/*STATIC*/ +void NimBLEDevice::removeIgnored(const NimBLEAddress &address) { for(auto it = m_ignoreList.begin(); it != m_ignoreList.end(); ++it) { if((*it).equals(address)){ m_ignoreList.erase(it); @@ -1065,6 +1144,7 @@ void NimBLEDevice::setOwnAddrType(uint8_t own_addr_type, bool useNRPA) { * @brief Set a custom callback for gap events. * @param [in] handler The function to call when gap events occur. */ +/*STATIC*/ void NimBLEDevice::setCustomGapHandler(gap_event_handler handler) { m_customGapHandler = handler; int rc = ble_gap_event_listener_register(&m_listener, m_customGapHandler, NULL); @@ -1076,5 +1156,4 @@ void NimBLEDevice::setCustomGapHandler(gap_event_handler handler) { } } // setCustomGapHandler - #endif // CONFIG_BT_ENABLED diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.h index 08a042fc2..94ad29478 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.h @@ -14,10 +14,9 @@ #ifndef MAIN_NIMBLEDEVICE_H_ #define MAIN_NIMBLEDEVICE_H_ -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" +#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) #include "NimBLEScan.h" @@ -39,7 +38,9 @@ #include "NimBLESecurity.h" #include "NimBLEAddress.h" -#include "esp_bt.h" +#ifdef ESP_PLATFORM +# include "esp_bt.h" +#endif #include #include @@ -110,8 +111,17 @@ public: static NimBLEServer* getServer(); #endif +#ifdef ESP_PLATFORM static void setPower(esp_power_level_t powerLevel, esp_ble_power_type_t powerType=ESP_BLE_PWR_TYPE_DEFAULT); static int getPower(esp_ble_power_type_t powerType=ESP_BLE_PWR_TYPE_DEFAULT); + static void setOwnAddrType(uint8_t own_addr_type, bool useNRPA=false); + static void setScanDuplicateCacheSize(uint16_t cacheSize); + static void setScanFilterMode(uint8_t type); +#else + static void setPower(int dbm); + static int getPower(); +#endif + static void setCustomGapHandler(gap_event_handler handler); static void setSecurityAuth(bool bonding, bool mitm, bool sc); static void setSecurityAuth(uint8_t auth_req); @@ -121,15 +131,12 @@ public: static void setSecurityPasskey(uint32_t pin); static uint32_t getSecurityPasskey(); static void setSecurityCallbacks(NimBLESecurityCallbacks* pCallbacks); - static void setOwnAddrType(uint8_t own_addr_type, bool useNRPA=false); static int startSecurity(uint16_t conn_id); static int setMTU(uint16_t mtu); static uint16_t getMTU(); static bool isIgnored(const NimBLEAddress &address); static void addIgnored(const NimBLEAddress &address); static void removeIgnored(const NimBLEAddress &address); - static void setScanDuplicateCacheSize(uint16_t cacheSize); - static void setScanFilterMode(uint8_t type); #if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) static NimBLEAdvertising* getAdvertising(); @@ -199,8 +206,10 @@ private: static ble_gap_event_listener m_listener; static gap_event_handler m_customGapHandler; static uint8_t m_own_addr_type; +#ifdef ESP_PLATFORM static uint16_t m_scanDuplicateSize; static uint8_t m_scanFilterMode; +#endif static std::vector m_whiteList; }; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp index a07294265..255131c02 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp @@ -11,12 +11,14 @@ * Created on: Mar 12, 2018 * Author: pcbreflux */ -#include "sdkconfig.h" + +#include "nimconfig.h" #if defined(CONFIG_BT_ENABLED) #include "NimBLEEddystoneTLM.h" #include "NimBLELog.h" +#include #include #define ENDIAN_CHANGE_U16(x) ((((x)&0xFF00)>>8) + (((x)&0xFF)<<8)) @@ -124,30 +126,30 @@ std::string NimBLEEddystoneTLM::toString() { out += " C\n"; out += "Adv. Count "; - snprintf(val, sizeof(val), "%d", ENDIAN_CHANGE_U32(m_eddystoneData.advCount)); + snprintf(val, sizeof(val), "%" PRIu32, ENDIAN_CHANGE_U32(m_eddystoneData.advCount)); out += val; out += "\n"; out += "Time in seconds "; - snprintf(val, sizeof(val), "%d", rawsec/10); + snprintf(val, sizeof(val), "%" PRIu32, rawsec/10); out += val; out += "\n"; out += "Time "; - snprintf(val, sizeof(val), "%04d", rawsec / 864000); + snprintf(val, sizeof(val), "%04" PRIu32, rawsec / 864000); out += val; out += "."; - snprintf(val, sizeof(val), "%02d", (rawsec / 36000) % 24); + snprintf(val, sizeof(val), "%02" PRIu32, (rawsec / 36000) % 24); out += val; out += ":"; - snprintf(val, sizeof(val), "%02d", (rawsec / 600) % 60); + snprintf(val, sizeof(val), "%02" PRIu32, (rawsec / 600) % 60); out += val; out += ":"; - snprintf(val, sizeof(val), "%02d", (rawsec / 10) % 60); + snprintf(val, sizeof(val), "%02" PRIu32, (rawsec / 10) % 60); out += val; out += "\n"; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneTLM.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneTLM.h index eb1cb0721..265c81b45 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneTLM.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneTLM.h @@ -14,6 +14,7 @@ #ifndef _NimBLEEddystoneTLM_H_ #define _NimBLEEddystoneTLM_H_ + #include "NimBLEUUID.h" #include diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneURL.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneURL.cpp index 7c3194c28..424df958e 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneURL.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneURL.cpp @@ -11,7 +11,7 @@ * Created on: Mar 12, 2018 * Author: pcbreflux */ -#include "sdkconfig.h" +#include "nimconfig.h" #if defined(CONFIG_BT_ENABLED) #include "NimBLEEddystoneURL.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEHIDDevice.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEHIDDevice.cpp index 37d0f52f5..78c8fea3c 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEHIDDevice.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEHIDDevice.cpp @@ -11,11 +11,9 @@ * Created on: Jan 03, 2018 * Author: chegewara */ -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #include "NimBLEHIDDevice.h" #include "NimBLE2904.h" @@ -29,7 +27,7 @@ NimBLEHIDDevice::NimBLEHIDDevice(NimBLEServer* server) { * Here we create mandatory services described in bluetooth specification */ m_deviceInfoService = server->createService(NimBLEUUID((uint16_t) 0x180a)); - m_hidService = server->createService(NimBLEUUID((uint16_t) 0x1812), 40); + m_hidService = server->createService(NimBLEUUID((uint16_t) 0x1812)); m_batteryService = server->createService(NimBLEUUID((uint16_t) 0x180f)); /* @@ -247,5 +245,4 @@ NimBLEService* NimBLEHIDDevice::batteryService() { return m_batteryService; } -#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) -#endif // #if defined(CONFIG_BT_ENABLED) +#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEHIDDevice.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEHIDDevice.h index 6ed7c2bde..ef2ed7395 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEHIDDevice.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEHIDDevice.h @@ -15,11 +15,8 @@ #ifndef _BLEHIDDEVICE_H_ #define _BLEHIDDEVICE_H_ -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) - #include "nimconfig.h" -#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) +#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) #include "NimBLECharacteristic.h" #include "NimBLEService.h" @@ -84,6 +81,6 @@ private: NimBLECharacteristic* m_protocolModeCharacteristic; //0x2a4e NimBLECharacteristic* m_batteryLevelCharacteristic; //0x2a19 }; -#endif // CONFIG_BT_NIMBLE_ROLE_BROADCASTER -#endif // CONFIG_BT_ENABLED + +#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER */ #endif /* _BLEHIDDEVICE_H_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLELog.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLELog.h index 8c1314634..0cedca940 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLELog.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLELog.h @@ -8,49 +8,11 @@ #ifndef MAIN_NIMBLELOG_H_ #define MAIN_NIMBLELOG_H_ -#include "sdkconfig.h" +#include "nimconfig.h" #if defined(CONFIG_BT_ENABLED) -#ifdef ARDUINO_ARCH_ESP32 -#include "syscfg/syscfg.h" -#include "modlog/modlog.h" - -// If Arduino is being used, strip out the colors and ignore log printing below ui setting. -// Note: because CONFIG_LOG_DEFAULT_LEVEL is set at ERROR in Arduino we must use MODLOG_DFLT(ERROR -// otherwise no messages will be printed above that level. - -#ifndef CORE_DEBUG_LEVEL -#define CORE_DEBUG_LEVEL CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL -#endif - -#if CORE_DEBUG_LEVEL >= 4 -#define NIMBLE_LOGD( tag, format, ... ) MODLOG_DFLT(ERROR, "D %s: "#format"\n",tag,##__VA_ARGS__) -#else -#define NIMBLE_LOGD( tag, format, ... ) (void)tag -#endif - -#if CORE_DEBUG_LEVEL >= 3 -#define NIMBLE_LOGI( tag, format, ... ) MODLOG_DFLT(ERROR, "I %s: "#format"\n",tag,##__VA_ARGS__) -#else -#define NIMBLE_LOGI( tag, format, ... ) (void)tag -#endif - -#if CORE_DEBUG_LEVEL >= 2 -#define NIMBLE_LOGW( tag, format, ... ) MODLOG_DFLT(ERROR, "W %s: "#format"\n",tag,##__VA_ARGS__) -#else -#define NIMBLE_LOGW( tag, format, ... ) (void)tag -#endif - -#if CORE_DEBUG_LEVEL >= 1 -#define NIMBLE_LOGE( tag, format, ... ) MODLOG_DFLT(ERROR, "E %s: "#format"\n",tag,##__VA_ARGS__) -#else -#define NIMBLE_LOGE( tag, format, ... ) (void)tag -#endif - -#define NIMBLE_LOGC( tag, format, ... ) MODLOG_DFLT(CRITICAL, "CRIT %s: "#format"\n",tag,##__VA_ARGS__) - -#else +#if defined(CONFIG_NIMBLE_CPP_IDF) // using esp-idf #include "esp_log.h" @@ -60,7 +22,51 @@ #define NIMBLE_LOGD(tag, format, ...) ESP_LOGD(tag, format, ##__VA_ARGS__) #define NIMBLE_LOGC(tag, format, ...) ESP_LOGE(tag, format, ##__VA_ARGS__) -#endif /*ARDUINO_ARCH_ESP32*/ +#else // using Arduino -#endif /*CONFIG_BT_ENABLED*/ -#endif /*MAIN_NIMBLELOG_H_*/ \ No newline at end of file +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/console/console.h" + +// If Arduino is being used, strip out the colors and ignore log printing below ui setting. +// Note: because CONFIG_LOG_DEFAULT_LEVEL is set at ERROR in Arduino we must use MODLOG_DFLT(ERROR +// otherwise no messages will be printed above that level. + +#ifndef NIMBLE_CPP_DEBUG_LEVEL + #if defined(ARDUINO_ARCH_ESP32) && defined(CORE_DEBUG_LEVEL) + #define NIMBLE_CPP_DEBUG_LEVEL CORE_DEBUG_LEVEL + #else + #define NIMBLE_CPP_DEBUG_LEVEL 0 + #endif +#endif + +#if NIMBLE_CPP_DEBUG_LEVEL >= 4 +#define NIMBLE_LOGD( tag, format, ... ) console_printf("D %s: "#format"\n",tag,##__VA_ARGS__) +#else +#define NIMBLE_LOGD( tag, format, ... ) (void)tag +#endif + +#if NIMBLE_CPP_DEBUG_LEVEL >= 3 +#define NIMBLE_LOGI( tag, format, ... ) console_printf("I %s: "#format"\n",tag,##__VA_ARGS__) +#else +#define NIMBLE_LOGI( tag, format, ... ) (void)tag +#endif + +#if NIMBLE_CPP_DEBUG_LEVEL >= 2 +#define NIMBLE_LOGW( tag, format, ... ) console_printf("W %s: "#format"\n",tag,##__VA_ARGS__) +#else +#define NIMBLE_LOGW( tag, format, ... ) (void)tag +#endif + +#if NIMBLE_CPP_DEBUG_LEVEL >= 1 +#define NIMBLE_LOGE( tag, format, ... ) console_printf("E %s: "#format"\n",tag,##__VA_ARGS__) +#define NIMBLE_LOGC( tag, format, ... ) console_printf("CRIT %s: "#format"\n",tag,##__VA_ARGS__) +#else +#define NIMBLE_LOGE( tag, format, ... ) (void)tag +#define NIMBLE_LOGC( tag, format, ... ) (void)tag +#endif + + + +#endif /* CONFIG_NIMBLE_CPP_IDF */ +#endif /* CONFIG_BT_ENABLED */ +#endif /* MAIN_NIMBLELOG_H_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.cpp index 85c854971..de5040672 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.cpp @@ -12,11 +12,8 @@ * Author: kolban */ -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) - #include "nimconfig.h" -#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) #include "NimBLERemoteCharacteristic.h" #include "NimBLEUtils.h" @@ -60,7 +57,6 @@ static const char* LOG_TAG = "NimBLERemoteCharacteristic"; m_pRemoteService = pRemoteService; m_notifyCallback = nullptr; m_timestamp = 0; - m_valMux = portMUX_INITIALIZER_UNLOCKED; NIMBLE_LOGD(LOG_TAG, "<< NimBLERemoteCharacteristic(): %s", m_uuid.toString().c_str()); } // NimBLERemoteCharacteristic @@ -408,12 +404,12 @@ NimBLEUUID NimBLERemoteCharacteristic::getUUID() { * @return The value of the remote characteristic. */ std::string NimBLERemoteCharacteristic::getValue(time_t *timestamp) { - portENTER_CRITICAL(&m_valMux); + ble_npl_hw_enter_critical(); std::string value = m_value; if(timestamp != nullptr) { *timestamp = m_timestamp; } - portEXIT_CRITICAL(&m_valMux); + ble_npl_hw_exit_critical(0); return value; } @@ -515,13 +511,13 @@ std::string NimBLERemoteCharacteristic::readValue(time_t *timestamp) { } while(rc != 0 && retryCount--); time_t t = time(nullptr); - portENTER_CRITICAL(&m_valMux); + ble_npl_hw_enter_critical(); m_value = value; m_timestamp = t; if(timestamp != nullptr) { *timestamp = m_timestamp; } - portEXIT_CRITICAL(&m_valMux); + ble_npl_hw_exit_critical(0); NIMBLE_LOGD(LOG_TAG, "<< readValue length: %d rc=%d", value.length(), rc); return value; @@ -819,6 +815,4 @@ int NimBLERemoteCharacteristic::onWriteCB(uint16_t conn_handle, return 0; } - -#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) -#endif /* CONFIG_BT_ENABLED */ +#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.h index 39e6d40fa..41ae816d4 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.h @@ -14,11 +14,9 @@ #ifndef COMPONENTS_NIMBLEREMOTECHARACTERISTIC_H_ #define COMPONENTS_NIMBLEREMOTECHARACTERISTIC_H_ -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) #include "NimBLERemoteService.h" #include "NimBLERemoteDescriptor.h" @@ -161,12 +159,10 @@ private: std::string m_value; notify_callback m_notifyCallback; time_t m_timestamp; - portMUX_TYPE m_valMux; // We maintain a vector of descriptors owned by this characteristic. std::vector m_descriptorVector; }; // NimBLERemoteCharacteristic -#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) -#endif /* CONFIG_BT_ENABLED */ +#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */ #endif /* COMPONENTS_NIMBLEREMOTECHARACTERISTIC_H_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteDescriptor.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteDescriptor.cpp index fc0f06b67..44b559000 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteDescriptor.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteDescriptor.cpp @@ -11,11 +11,9 @@ * Created on: Jul 8, 2017 * Author: kolban */ -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) #include "NimBLERemoteDescriptor.h" #include "NimBLEUtils.h" @@ -188,6 +186,7 @@ int NimBLERemoteDescriptor::onReadCB(uint16_t conn_handle, const struct ble_gatt_error *error, struct ble_gatt_attr *attr, void *arg) { + (void)attr; ble_task_data_t *pTaskData = (ble_task_data_t*)arg; NimBLERemoteDescriptor* desc = (NimBLERemoteDescriptor*)pTaskData->pATT; uint16_t conn_id = desc->getRemoteCharacteristic()->getRemoteService()->getClient()->getConnId(); @@ -350,5 +349,4 @@ bool NimBLERemoteDescriptor::writeValue(const std::string &newValue, bool respon return writeValue((uint8_t*) newValue.data(), newValue.length(), response); } // writeValue -#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) -#endif /* CONFIG_BT_ENABLED */ +#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteDescriptor.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteDescriptor.h index b52738ef7..13e83516d 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteDescriptor.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteDescriptor.h @@ -14,11 +14,9 @@ #ifndef COMPONENTS_NIMBLEREMOTEDESCRIPTOR_H_ #define COMPONENTS_NIMBLEREMOTEDESCRIPTOR_H_ -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) #include "NimBLERemoteCharacteristic.h" @@ -81,6 +79,5 @@ private: NimBLERemoteCharacteristic* m_pRemoteCharacteristic; }; -#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) -#endif /* CONFIG_BT_ENABLED */ +#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */ #endif /* COMPONENTS_NIMBLEREMOTEDESCRIPTOR_H_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteService.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteService.cpp index efb6662a8..b8ae4fce5 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteService.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteService.cpp @@ -11,11 +11,9 @@ * Created on: Jul 8, 2017 * Author: kolban */ -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) #include "NimBLERemoteService.h" #include "NimBLEUtils.h" @@ -386,6 +384,4 @@ std::string NimBLERemoteService::toString() { return res; } // toString - -#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) -#endif /* CONFIG_BT_ENABLED */ +#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteService.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteService.h index 751c9effb..0443cfd99 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteService.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteService.h @@ -14,11 +14,9 @@ #ifndef COMPONENTS_NIMBLEREMOTESERVICE_H_ #define COMPONENTS_NIMBLEREMOTESERVICE_H_ -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) #include "NimBLEClient.h" #include "NimBLEUUID.h" @@ -83,6 +81,5 @@ private: uint16_t m_endHandle; }; // NimBLERemoteService -#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) -#endif /* CONFIG_BT_ENABLED */ +#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */ #endif /* COMPONENTS_NIMBLEREMOTESERVICE_H_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEScan.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEScan.cpp index 037055208..d9dcb7de4 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEScan.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEScan.cpp @@ -11,11 +11,9 @@ * Created on: Jul 1, 2017 * Author: kolban */ -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) +#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) #include "NimBLEScan.h" #include "NimBLEDevice.h" @@ -534,5 +532,4 @@ NimBLEAdvertisedDevice *NimBLEScanResults::getDevice(const NimBLEAddress &addres return nullptr; } -#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) -#endif /* CONFIG_BT_ENABLED */ +#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_OBSERVER */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEScan.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEScan.h index 49d67c8ec..76a114276 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEScan.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEScan.h @@ -13,16 +13,18 @@ */ #ifndef COMPONENTS_NIMBLE_SCAN_H_ #define COMPONENTS_NIMBLE_SCAN_H_ -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) +#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) #include "NimBLEAdvertisedDevice.h" #include "NimBLEUtils.h" +#if defined(CONFIG_NIMBLE_CPP_IDF) #include "host/ble_gap.h" +#else +#include "nimble/nimble/host/include/host/ble_gap.h" +#endif #include @@ -97,6 +99,5 @@ private: uint8_t m_maxResults; }; -#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) -#endif /* CONFIG_BT_ENABLED */ +#endif /* CONFIG_BT_ENABLED CONFIG_BT_NIMBLE_ROLE_OBSERVER */ #endif /* COMPONENTS_NIMBLE_SCAN_H_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLESecurity.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLESecurity.cpp index aa0629698..df6d192b4 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLESecurity.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLESecurity.cpp @@ -12,7 +12,7 @@ * Author: chegewara */ -#include "sdkconfig.h" +#include "nimconfig.h" #if defined(CONFIG_BT_ENABLED) #include "NimBLESecurity.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLESecurity.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLESecurity.h index 5a7619f45..157577d7b 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLESecurity.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLESecurity.h @@ -14,10 +14,16 @@ #ifndef COMPONENTS_NIMBLESECURITY_H_ #define COMPONENTS_NIMBLESECURITY_H_ -#include "sdkconfig.h" + +#include "nimconfig.h" #if defined(CONFIG_BT_ENABLED) +#if defined(CONFIG_NIMBLE_CPP_IDF) #include "host/ble_gap.h" +#else +#include "nimble/nimble/host/include/host/ble_gap.h" +#endif + /**** FIX COMPILATION ****/ #undef min #undef max diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.cpp index 082c51ad8..e31c81b45 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.cpp @@ -12,19 +12,20 @@ * Author: kolban */ -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) - #include "nimconfig.h" -#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #include "NimBLEServer.h" #include "NimBLEDevice.h" #include "NimBLELog.h" +#if defined(CONFIG_NIMBLE_CPP_IDF) #include "services/gap/ble_svc_gap.h" #include "services/gatt/ble_svc_gatt.h" - +#else +#include "nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h" +#include "nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h" +#endif static const char* LOG_TAG = "NimBLEServer"; static NimBLEServerCallbacks defaultCallbacks; @@ -79,18 +80,17 @@ NimBLEService* NimBLEServer::createService(const char* uuid) { * to provide inst_id value different for each service. * @return A reference to the new service object. */ -NimBLEService* NimBLEServer::createService(const NimBLEUUID &uuid, uint32_t numHandles, uint8_t inst_id) { +NimBLEService* NimBLEServer::createService(const NimBLEUUID &uuid) { NIMBLE_LOGD(LOG_TAG, ">> createService - %s", uuid.toString().c_str()); - // TODO: add functionality to use inst_id for multiple services with same uuid - (void)inst_id; + // Check that a service with the supplied UUID does not already exist. if(getServiceByUUID(uuid) != nullptr) { NIMBLE_LOGW(LOG_TAG, "Warning creating a duplicate service UUID: %s", std::string(uuid).c_str()); } - NimBLEService* pService = new NimBLEService(uuid, numHandles, this); - m_svcVec.push_back(pService); // Save a reference to this service being on this server. + NimBLEService* pService = new NimBLEService(uuid); + m_svcVec.push_back(pService); serviceChanged(); NIMBLE_LOGD(LOG_TAG, "<< createService"); @@ -734,7 +734,7 @@ void NimBLEServer::startAdvertising() { */ void NimBLEServer::stopAdvertising() { NimBLEDevice::stopAdvertising(); -} // startAdvertising +} // stopAdvertising /** @@ -772,7 +772,30 @@ void NimBLEServer::updateConnParams(uint16_t conn_handle, if(rc != 0) { NIMBLE_LOGE(LOG_TAG, "Update params error: %d, %s", rc, NimBLEUtils::returnCodeToString(rc)); } -}// updateConnParams +} // updateConnParams + + +/** + * @brief Request an update of the data packet length. + * * Can only be used after a connection has been established. + * @details Sends a data length update request to the peer. + * The Data Length Extension (DLE) allows to increase the Data Channel Payload from 27 bytes to up to 251 bytes. + * The peer needs to support the Bluetooth 4.2 specifications, to be capable of DLE. + * @param [in] conn_handle The connection handle of the peer to send the request to. + * @param [in] tx_octets The preferred number of payload octets to use (Range 0x001B-0x00FB). + */ +void NimBLEServer::setDataLen(uint16_t conn_handle, uint16_t tx_octets) { +#ifdef CONFIG_NIMBLE_CPP_IDF // not yet available in IDF, Sept 9 2021 + return; +#else + uint16_t tx_time = (tx_octets + 14) * 8; + + int rc = ble_gap_set_data_len(conn_handle, tx_octets, tx_time); + if(rc != 0) { + NIMBLE_LOGE(LOG_TAG, "Set data length error: %d, %s", rc, NimBLEUtils::returnCodeToString(rc)); + } +#endif +} // setDataLen bool NimBLEServer::setIndicateWait(uint16_t conn_handle) { @@ -842,6 +865,4 @@ bool NimBLEServerCallbacks::onConfirmPIN(uint32_t pin){ return true; } - -#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) -#endif // CONFIG_BT_ENABLED +#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.h index ebcf39f23..5054b844e 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.h @@ -14,11 +14,9 @@ #ifndef MAIN_NIMBLESERVER_H_ #define MAIN_NIMBLESERVER_H_ -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #define NIMBLE_ATT_REMOVE_HIDE 1 #define NIMBLE_ATT_REMOVE_DELETE 2 @@ -43,8 +41,7 @@ class NimBLEServer { public: size_t getConnectedCount(); NimBLEService* createService(const char* uuid); - NimBLEService* createService(const NimBLEUUID &uuid, uint32_t numHandles=15, - uint8_t inst_id=0); + NimBLEService* createService(const NimBLEUUID &uuid); void removeService(NimBLEService* service, bool deleteSvc = false); void addService(NimBLEService* service); NimBLEAdvertising* getAdvertising(); @@ -61,6 +58,7 @@ public: void updateConnParams(uint16_t conn_handle, uint16_t minInterval, uint16_t maxInterval, uint16_t latency, uint16_t timeout); + void setDataLen(uint16_t conn_handle, uint16_t tx_octets); uint16_t getPeerMTU(uint16_t conn_id); std::vector getPeerDevices(); NimBLEConnInfo getPeerInfo(size_t index); @@ -168,7 +166,5 @@ public: virtual bool onConfirmPIN(uint32_t pin); }; // NimBLEServerCallbacks - -#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) -#endif /* CONFIG_BT_ENABLED */ +#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */ #endif /* MAIN_NIMBLESERVER_H_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEService.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEService.cpp index 9c43e900c..18e15bcbd 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEService.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEService.cpp @@ -14,12 +14,10 @@ // A service is identified by a UUID. A service is also the container for one or more characteristics. -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) - #include "nimconfig.h" -#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#include "NimBLEDevice.h" #include "NimBLEService.h" #include "NimBLEUtils.h" #include "NimBLELog.h" @@ -34,25 +32,19 @@ static const char* LOG_TAG = "NimBLEService"; // Tag for logging. /** * @brief Construct an instance of the NimBLEService * @param [in] uuid The UUID of the service. - * @param [in] numHandles The maximum number of handles associated with the service. - * @param [in] pServer A pointer to the server instance that this service belongs to. */ -NimBLEService::NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer) -: NimBLEService(NimBLEUUID(uuid), numHandles, pServer) { +NimBLEService::NimBLEService(const char* uuid) +: NimBLEService(NimBLEUUID(uuid)) { } /** * @brief Construct an instance of the BLEService * @param [in] uuid The UUID of the service. - * @param [in] numHandles The maximum number of handles associated with the service. - * @param [in] pServer A pointer to the server instance that this service belongs to. */ -NimBLEService::NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer) { +NimBLEService::NimBLEService(const NimBLEUUID &uuid) { m_uuid = uuid; m_handle = NULL_HANDLE; - m_pServer = pServer; - m_numHandles = numHandles; m_pSvcDef = nullptr; m_removed = 0; @@ -429,8 +421,7 @@ std::string NimBLEService::toString() { * @return The BLEServer associated with this service. */ NimBLEServer* NimBLEService::getServer() { - return m_pServer; + return NimBLEDevice::getServer(); }// getServer -#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) -#endif // CONFIG_BT_ENABLED +#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEService.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEService.h index ebf913d32..fbdd2e1bd 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEService.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEService.h @@ -14,11 +14,9 @@ #ifndef MAIN_NIMBLESERVICE_H_ #define MAIN_NIMBLESERVICE_H_ -#include "sdkconfig.h" -#if defined(CONFIG_BT_ENABLED) #include "nimconfig.h" -#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #include "NimBLEServer.h" #include "NimBLECharacteristic.h" @@ -36,8 +34,8 @@ class NimBLECharacteristic; class NimBLEService { public: - NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer); - NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer); + NimBLEService(const char* uuid); + NimBLEService(const NimBLEUUID &uuid); ~NimBLEService(); NimBLEServer* getServer(); @@ -76,16 +74,12 @@ private: friend class NimBLEDevice; uint16_t m_handle; - NimBLEServer* m_pServer; NimBLEUUID m_uuid; - uint16_t m_numHandles; ble_gatt_svc_def* m_pSvcDef; uint8_t m_removed; std::vector m_chrVec; }; // NimBLEService - -#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) -#endif // CONFIG_BT_ENABLED +#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */ #endif /* MAIN_NIMBLESERVICE_H_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUUID.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUUID.cpp index 9338d7d00..4234650d8 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUUID.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUUID.cpp @@ -11,7 +11,8 @@ * Created on: Jun 21, 2017 * Author: kolban */ -#include "sdkconfig.h" + +#include "nimconfig.h" #if defined(CONFIG_BT_ENABLED) #include "NimBLEUtils.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUUID.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUUID.h index 982f9c36d..724db19fd 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUUID.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUUID.h @@ -14,10 +14,16 @@ #ifndef COMPONENTS_NIMBLEUUID_H_ #define COMPONENTS_NIMBLEUUID_H_ -#include "sdkconfig.h" + +#include "nimconfig.h" #if defined(CONFIG_BT_ENABLED) +#if defined(CONFIG_NIMBLE_CPP_IDF) #include "host/ble_uuid.h" +#else +#include "nimble/nimble/host/include/host/ble_uuid.h" +#endif + /**** FIX COMPILATION ****/ #undef min #undef max diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUtils.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUtils.cpp index 7a1f55b41..c6bd823ff 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUtils.cpp +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUtils.cpp @@ -6,12 +6,13 @@ * */ -#include "sdkconfig.h" +#include "nimconfig.h" #if defined(CONFIG_BT_ENABLED) #include "NimBLEUtils.h" #include "NimBLELog.h" -#include "nimconfig.h" + +#include static const char* LOG_TAG = "NimBLEUtils"; @@ -342,6 +343,7 @@ const char* NimBLEUtils::returnCodeToString(int rc) { return "Unknown"; } #else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT) + (void)rc; return ""; #endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT) } @@ -369,6 +371,7 @@ const char* NimBLEUtils::advTypeToString(uint8_t advType) { return "Unknown flag"; } #else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT) + (void)advType; return ""; #endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT) } // adFlagsToString @@ -416,8 +419,11 @@ char* NimBLEUtils::buildHexData(uint8_t* target, const uint8_t* source, uint8_t * @param [in] arg Unused. */ void NimBLEUtils::dumpGapEvent(ble_gap_event *event, void *arg){ + (void)arg; #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT) NIMBLE_LOGD(LOG_TAG, "Received a GAP event: %s", gapEventToString(event->type)); +#else + (void)event; #endif } @@ -504,6 +510,7 @@ const char* NimBLEUtils::gapEventToString(uint8_t eventType) { return "Unknown event type"; } #else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT) + (void)eventType; return ""; #endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT) } // gapEventToString diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUtils.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUtils.h index acbc93e72..2fe4b3c41 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUtils.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUtils.h @@ -8,10 +8,15 @@ #ifndef COMPONENTS_NIMBLEUTILS_H_ #define COMPONENTS_NIMBLEUTILS_H_ -#include "sdkconfig.h" + +#include "nimconfig.h" #if defined(CONFIG_BT_ENABLED) +#if defined(CONFIG_NIMBLE_CPP_IDF) #include "host/ble_gap.h" +#else +#include "nimble/nimble/host/include/host/ble_gap.h" +#endif /**** FIX COMPILATION ****/ #undef min diff --git a/lib/libesp32_div/NimBLE-Arduino/src/console/console.h b/lib/libesp32_div/NimBLE-Arduino/src/console/console.h deleted file mode 100644 index 96f965159..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/console/console.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2019 Espressif Systems (Shanghai) PTE LTD -// -//Licensed under the Apache License, Version 2.0 (the "License"); -//you may not use this file except in compliance with the License. -//You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -//Unless required by applicable law or agreed to in writing, software -//distributed under the License is distributed on an "AS IS" BASIS, -//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -//See the License for the specific language governing permissions and -//limitations under the License. -#ifndef _CONSOLE_H -#define _CONSOLE_H - -#include - -#define console_printf printf - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/esp_compiler.h b/lib/libesp32_div/NimBLE-Arduino/src/esp_compiler.h deleted file mode 100644 index 94ec29c23..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/esp_compiler.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2016-2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#ifndef __ESP_COMPILER_H -#define __ESP_COMPILER_H - -/* - * The likely and unlikely macro pairs: - * These macros are useful to place when application - * knows the majority ocurrence of a decision paths, - * placing one of these macros can hint the compiler - * to reorder instructions producing more optimized - * code. - */ -#if (CONFIG_COMPILER_OPTIMIZATION_PERF) -#define likely(x) __builtin_expect(!!(x), 1) -#define unlikely(x) __builtin_expect(!!(x), 0) -#else -#define likely(x) (x) -#define unlikely(x) (x) -#endif - -#endif \ No newline at end of file diff --git a/lib/libesp32_div/NimBLE-Arduino/src/CODING_STANDARDS.md b/lib/libesp32_div/NimBLE-Arduino/src/nimble/CODING_STANDARDS.md similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/CODING_STANDARDS.md rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/CODING_STANDARDS.md diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/LICENSE b/lib/libesp32_div/NimBLE-Arduino/src/nimble/LICENSE new file mode 100644 index 000000000..08b9b218a --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/LICENSE @@ -0,0 +1,217 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +This product bundles queue.h 8.5, which is available under the "3-clause BSD" +license. For details, see porting/nimble/include/os/queue.h + +This product partly derives from FreeBSD, which is available under the +"3-clause BSD" license. For details, see: + * porting/nimble/src/os_mbuf.c + +This product bundles Gary S. Brown's CRC32 implementation, which is available +under the following license: + COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or + code or tables extracted from it, as desired without restriction. + +This product bundles tinycrypt, which is available under the "3-clause BSD" +license. For details, and bundled files see: + * ext/tinycrypt/LICENSE diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NOTICE b/lib/libesp32_div/NimBLE-Arduino/src/nimble/NOTICE similarity index 61% rename from lib/libesp32_div/NimBLE-Arduino/src/NOTICE rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/NOTICE index fc24c6abc..02fe5929d 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/NOTICE +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/NOTICE @@ -1,5 +1,6 @@ Apache Mynewt NimBLE -Copyright 2015-2018 The Apache Software Foundation +Copyright 2015-2020 The Apache Software Foundation +Modifications Copyright 2017-2020 Espressif Systems (Shanghai) CO., LTD. This product includes software developed at The Apache Software Foundation (http://www.apache.org/). diff --git a/lib/libesp32_div/NimBLE-Arduino/src/README.md b/lib/libesp32_div/NimBLE-Arduino/src/nimble/README.md similarity index 90% rename from lib/libesp32_div/NimBLE-Arduino/src/README.md rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/README.md index bbd17fc85..37103be08 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/README.md +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/README.md @@ -23,7 +23,7 @@ ## Overview -Apache NimBLE is an open-source Bluetooth 5.0 stack (both Host & Controller) +Apache NimBLE is an open-source Bluetooth 5.1 stack (both Host & Controller) that completely replaces the proprietary SoftDevice on Nordic chipsets. It is part of [Apache Mynewt project](https://github.com/apache/mynewt-core). @@ -33,7 +33,6 @@ Features highlight: - Support for up to 32 simultaneous connections. - Legacy and SC (secure connections) SMP support (pairing and bonding). - Advertising Extensions. - - Periodic Advertising. - Coded (aka Long Range) and 2M PHYs. - Bluetooth Mesh. @@ -84,27 +83,24 @@ There are also some sample applications that show how to Apache Mynewt NimBLE stack. These sample applications are located in the `apps/` directory of Apache Mynewt [repo](https://github.com/apache/mynewt-core). Some examples: -* [blecent](https://github.com/apache/mynewt-core/tree/master/apps/blecent): +* [blecent](https://github.com/apache/mynewt-nimble/tree/master/apps/blecent): A basic central device with no user interface. This application scans for a peripheral that supports the alert notification service (ANS). Upon discovering such a peripheral, blecent connects and performs a characteristic read, characteristic write, and notification subscription. -* [blehci](https://github.com/apache/mynewt-core/tree/master/apps/blehci): +* [blehci](https://github.com/apache/mynewt-nimble/tree/master/apps/blehci): Implements a BLE controller-only application. A separate host-only implementation, such as Linux's BlueZ, can interface with this application via HCI over UART. -* [bleprph](https://github.com/apache/mynewt-core/tree/master/apps/bleprph): An +* [bleprph](https://github.com/apache/mynewt-nimble/tree/master/apps/bleprph): An implementation of a minimal BLE peripheral. -* [btshell](https://github.com/apache/mynewt-core/tree/master/apps/btshell): A +* [btshell](https://github.com/apache/mynewt-nimble/tree/master/apps/btshell): A shell-like application allowing to configure and use most of NimBLE functionality from command line. * [bleuart](https://github.com/apache/mynewt-core/tree/master/apps/bleuart): Implements a simple BLE peripheral that supports the Nordic UART / Serial Port Emulation service (https://developer.nordicsemi.com/nRF5_SDK/nRF51_SDK_v8.x.x/doc/8.0.0/s110/html/a00072.html). -* [test](https://github.com/apache/mynewt-core/tree/master/apps/test): Test - project which can be compiled either with the simulator, or on a per-architecture basis. - Test will run all the package's unit tests. # Getting Help @@ -113,7 +109,7 @@ want to talk to a human about what you're working on, you can contact us via the [developers mailing list](mailto:dev@mynewt.apache.org). Although not a formal channel, you can also find a number of core developers -on the #mynewt channel on Freenode IRC or #general channel on [Mynewt Slack](https://join.slack.com/mynewt/shared_invite/MTkwMTg1ODM1NTg5LTE0OTYxNzQ4NzQtZTU1YmNhYjhkMg) +on the #mynewt channel on Freenode IRC or #general channel on [Mynewt Slack](https://mynewt.slack.com/join/shared_invite/enQtNjA1MTg0NzgyNzg3LTcyMmZiOGQzOGMxM2U4ODFmMTIwNjNmYTE5Y2UwYjQwZWIxNTE0MTUzY2JmMTEzOWFjYWZkNGM0YmM4MzAxNWQ) Also, be sure to checkout the [Frequently Asked Questions](https://mynewt.apache.org/faq/answers) for some help troubleshooting first. diff --git a/lib/libesp32_div/NimBLE-Arduino/src/RELEASE_NOTES.md b/lib/libesp32_div/NimBLE-Arduino/src/nimble/RELEASE_NOTES.md similarity index 56% rename from lib/libesp32_div/NimBLE-Arduino/src/RELEASE_NOTES.md rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/RELEASE_NOTES.md index cda8fe2e4..3bdd31ad0 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/RELEASE_NOTES.md +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/RELEASE_NOTES.md @@ -1,26 +1,32 @@ # RELEASE NOTES -16 July 2019 - Apache NimBLE v1.2.0 +18 March 2020 - Apache NimBLE v1.3.0 For full release notes, please visit the [Apache Mynewt Wiki](https://cwiki.apache.org/confluence/display/MYNEWT/Release+Notes). -Apache NimBLE is an open-source Bluetooth 5.0 stack (both Host & Controller) that completely +Apache NimBLE is an open-source Bluetooth 5.1 stack (both Host & Controller) that completely replaces the proprietary SoftDevice on Nordic chipsets. New features in this version of NimBLE include: -* Perdiodic Advertising support with up to 1650 bytes of data (scanner and advertiser) -* Support for scan request notification in GAP API -* Updated host qualification ID +* Support for Bluetooth Core Specification 5.1 +* New blestress test application +* Dialog DA1469x CMAC driver +* Support for LE Secure Connections out-of-band (OOB) association model +* Support for automated generation of syscfg for ports * Qualification related bugfixes -* GAP API doxygen documentation update * BLE Mesh improvements - fixes and resync with latest Zephyr code * RIOT OS port fixes and improvements * btshell sample application improvements * improvements for bttester application * Controller duplicates filtering improvements -* Memory and CPU usage optimizations in controller +* Multi PHY support improvements +* Memory and CPU usage optimizations +* Use of packed structs for HCI (code size reduction) +* Linux sample improvements +* PTS test instructions updates +* Clock managements improvements in controller If working on next-generation RTOS and Bluetooth protocol stack sounds exciting to you, get in touch, by sending a mail to the Apache Mynewt diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/console/console.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/console/console.h new file mode 100644 index 000000000..b1052e62e --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/console/console.h @@ -0,0 +1,16 @@ +#ifndef __CONSOLE_H__ +#define __CONSOLE_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define console_printf printf + +#ifdef __cplusplus +} +#endif + +#endif /* __CONSOLE_H__ */ \ No newline at end of file diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/esp-hci/include/esp_compiler.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/esp-hci/include/esp_compiler.h new file mode 100644 index 000000000..7ab8cb9af --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/esp-hci/include/esp_compiler.h @@ -0,0 +1,51 @@ +// Copyright 2016-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef __ESP_COMPILER_H +#define __ESP_COMPILER_H + +/* + * The likely and unlikely macro pairs: + * These macros are useful to place when application + * knows the majority ocurrence of a decision paths, + * placing one of these macros can hint the compiler + * to reorder instructions producing more optimized + * code. + */ +#if (CONFIG_COMPILER_OPTIMIZATION_PERF) +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) +#else +#define likely(x) (x) +#define unlikely(x) (x) +#endif + +/* + * Utility macros used for designated initializers, which work differently + * in C99 and C++ standards mainly for aggregate types. + * The member separator, comma, is already part of the macro, please omit the trailing comma. + * Usage example: + * struct config_t { char* pchr; char arr[SIZE]; } config = { + * ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(pchr) + * ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_STR(arr, "Value") + * }; + */ +#ifdef __cplusplus +#define ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_STR(member, value) { .member = value }, +#define ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(member) .member = { }, +#else +#define ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_STR(member, value) .member = value, +#define ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(member) +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/esp_nimble_hci.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/esp-hci/include/esp_nimble_hci.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/esp_nimble_hci.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/esp-hci/include/esp_nimble_hci.h index e10436f3c..dda03216e 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/esp_nimble_hci.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/esp-hci/include/esp_nimble_hci.h @@ -19,10 +19,11 @@ * under the License. */ +#ifdef ESP_PLATFORM #ifndef __ESP_NIMBLE_HCI_H__ #define __ESP_NIMBLE_HCI_H__ -#include "nimble/ble_hci_trans.h" +#include "nimble/nimble/include/nimble/ble_hci_trans.h" #ifdef __cplusplus extern "C" { @@ -136,3 +137,4 @@ esp_err_t esp_nimble_hci_and_controller_deinit(void); #endif #endif /* __ESP_NIMBLE_HCI_H__ */ +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/esp-hci/src/esp_nimble_hci.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/esp-hci/src/esp_nimble_hci.c similarity index 96% rename from lib/libesp32_div/NimBLE-Arduino/src/esp-hci/src/esp_nimble_hci.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/esp-hci/src/esp_nimble_hci.c index 2963e15b3..f4df29a65 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/esp-hci/src/esp_nimble_hci.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/esp-hci/src/esp_nimble_hci.c @@ -19,17 +19,19 @@ * under the License. */ +#ifdef ESP_PLATFORM + #include -#include "sysinit/sysinit.h" -#include "nimble/hci_common.h" -#include "host/ble_hs.h" -#include "nimble/nimble_port.h" -#include "nimble/nimble_port_freertos.h" -#include "esp_nimble_hci.h" -#include "esp_nimble_mem.h" -#include "esp_bt.h" -#include "freertos/semphr.h" -#include "esp_compiler.h" +#include "nimble/porting/nimble/include/sysinit/sysinit.h" +#include "nimble/nimble/include/nimble/hci_common.h" +#include "nimble/nimble/host/include/host/ble_hs.h" +#include "nimble/porting/nimble/include/nimble/nimble_port.h" +#include "nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h" +#include "../include/esp_nimble_hci.h" +#include "../../port/include/esp_nimble_mem.h" +#include +#include +#include "../include/esp_compiler.h" /* IPC is used to improve performance when calls come from a processor not running the NimBLE stack */ /* but does not exist for solo */ #ifndef CONFIG_FREERTOS_UNICORE @@ -310,7 +312,6 @@ static struct os_mbuf *ble_hci_trans_acl_buf_alloc(void) static void ble_hci_rx_acl(uint8_t *data, uint16_t len) { struct os_mbuf *m; - int rc; int sr; if (len < BLE_HCI_DATA_HDR_SZ || len > MYNEWT_VAL(BLE_ACL_BUF_SIZE)) { return; @@ -319,11 +320,9 @@ static void ble_hci_rx_acl(uint8_t *data, uint16_t len) m = ble_hci_trans_acl_buf_alloc(); if (!m) { - ESP_LOGE(TAG, "%s failed to allocate ACL buffers; increase ACL_BUF_COUNT", __func__); return; } - if ((rc = os_mbuf_append(m, data, len)) != 0) { - ESP_LOGE(TAG, "%s failed to os_mbuf_append; rc = %d", __func__, rc); + if (os_mbuf_append(m, data, len)) { os_mbuf_free_chain(m); return; } @@ -531,7 +530,6 @@ esp_err_t esp_nimble_hci_and_controller_init(void) if ((ret = esp_bt_controller_enable(ESP_BT_MODE_BLE)) != ESP_OK) { return ret; } - return esp_nimble_hci_init(); } @@ -593,3 +591,5 @@ esp_err_t esp_nimble_hci_and_controller_deinit(void) return ESP_OK; } + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/esp_nimble_cfg.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/include/esp_nimble_cfg.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/esp_nimble_cfg.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/include/esp_nimble_cfg.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/esp_nimble_mem.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/include/esp_nimble_mem.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/esp_nimble_mem.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/include/esp_nimble_mem.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/port/src/esp_nimble_mem.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/src/esp_nimble_mem.c similarity index 96% rename from lib/libesp32_div/NimBLE-Arduino/src/port/src/esp_nimble_mem.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/src/esp_nimble_mem.c index a26e9b2f4..21e22fd26 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/port/src/esp_nimble_mem.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/src/esp_nimble_mem.c @@ -18,11 +18,12 @@ * specific language governing permissions and limitations * under the License. */ +#ifdef ESP_PLATFORM #include "esp_attr.h" #include "esp_heap_caps.h" #include "nimconfig.h" -#include "esp_nimble_mem.h" +#include "../include/esp_nimble_mem.h" IRAM_ATTR void *nimble_platform_mem_malloc(size_t size) { @@ -54,3 +55,4 @@ IRAM_ATTR void nimble_platform_mem_free(void *ptr) { heap_caps_free(ptr); } +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/AUTHORS b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/AUTHORS similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/AUTHORS rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/AUTHORS diff --git a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/LICENSE b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/LICENSE similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/LICENSE rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/LICENSE diff --git a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/README b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/README similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/README rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/README diff --git a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/VERSION b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/VERSION similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/VERSION rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/VERSION diff --git a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/documentation/tinycrypt.rst b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/documentation/tinycrypt.rst similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/documentation/tinycrypt.rst rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/documentation/tinycrypt.rst diff --git a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/aes.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/aes.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/aes.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/aes.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/cbc_mode.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/cbc_mode.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/cbc_mode.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/cbc_mode.h index 4a837fd01..a53318eed 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/cbc_mode.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/cbc_mode.h @@ -74,7 +74,7 @@ #ifndef __TC_CBC_MODE_H__ #define __TC_CBC_MODE_H__ -#include +#include "aes.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ccm_mode.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ccm_mode.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ccm_mode.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ccm_mode.h index 69c798e2f..c22ac08d4 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ccm_mode.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ccm_mode.h @@ -74,7 +74,7 @@ #ifndef __TC_CCM_MODE_H__ #define __TC_CCM_MODE_H__ -#include +#include "aes.h" #include #ifdef __cplusplus diff --git a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/cmac_mode.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/cmac_mode.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/cmac_mode.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/cmac_mode.h index f44b0a53c..327097026 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/cmac_mode.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/cmac_mode.h @@ -97,7 +97,7 @@ #ifndef __TC_CMAC_MODE_H__ #define __TC_CMAC_MODE_H__ -#include +#include "aes.h" #include diff --git a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/constants.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/constants.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/constants.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/constants.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ctr_mode.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_mode.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ctr_mode.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_mode.h index dc221f9ee..e2da5b43b 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ctr_mode.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_mode.h @@ -67,8 +67,8 @@ #ifndef __TC_CTR_MODE_H__ #define __TC_CTR_MODE_H__ -#include -#include +#include "aes.h" +#include "constants.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ctr_prng.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_prng.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ctr_prng.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_prng.h index 9be06dbb1..bff7f9726 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ctr_prng.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_prng.h @@ -59,7 +59,7 @@ #ifndef __TC_CTR_PRNG_H__ #define __TC_CTR_PRNG_H__ -#include +#include "aes.h" #define TC_CTR_PRNG_RESEED_REQ -1 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ecc.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ecc.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc_dh.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dh.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc_dh.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dh.h index b828e195d..930e9162e 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc_dh.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dh.h @@ -69,7 +69,7 @@ #ifndef __TC_ECC_DH_H__ #define __TC_ECC_DH_H__ -#include +#include "ecc.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc_dsa.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dsa.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc_dsa.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dsa.h index aca00bc95..8cb421b7a 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc_dsa.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dsa.h @@ -78,7 +78,7 @@ #ifndef __TC_ECC_DSA_H__ #define __TC_ECC_DSA_H__ -#include +#include "ecc.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc_platform_specific.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_platform_specific.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/ecc_platform_specific.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_platform_specific.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/hmac.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/hmac.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/hmac.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/hmac.h index 3a081494a..cfa7d38cd 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/hmac.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/hmac.h @@ -63,7 +63,7 @@ #ifndef __TC_HMAC_H__ #define __TC_HMAC_H__ -#include +#include "sha256.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/hmac_prng.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/hmac_prng.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/hmac_prng.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/hmac_prng.h index ad12cbbf0..24f417e6b 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/hmac_prng.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/hmac_prng.h @@ -68,8 +68,8 @@ #ifndef __TC_HMAC_PRNG_H__ #define __TC_HMAC_PRNG_H__ -#include -#include +#include "sha256.h" +#include "hmac.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/sha256.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/sha256.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/sha256.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/sha256.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/utils.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/utils.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/utils.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/include/tinycrypt/utils.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/aes_decrypt.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/aes_decrypt.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/aes_decrypt.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/aes_decrypt.c index 993a6180c..0bab6e280 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/aes_decrypt.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/aes_decrypt.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include +#include "../include/tinycrypt/aes.h" +#include "../include/tinycrypt/constants.h" +#include "../include/tinycrypt/utils.h" static const uint8_t inv_sbox[256] = { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, diff --git a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/aes_encrypt.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/aes_encrypt.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/aes_encrypt.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/aes_encrypt.c index 8991aee52..bdc434bce 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/aes_encrypt.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/aes_encrypt.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include +#include "../include/tinycrypt/aes.h" +#include "../include/tinycrypt/utils.h" +#include "../include/tinycrypt/constants.h" static const uint8_t sbox[256] = { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, diff --git a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/cbc_mode.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/cbc_mode.c similarity index 96% rename from lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/cbc_mode.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/cbc_mode.c index 62d7879eb..b743878a9 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/cbc_mode.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/cbc_mode.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include +#include "../include/tinycrypt/cbc_mode.h" +#include "../include/tinycrypt/constants.h" +#include "../include/tinycrypt/utils.h" int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in, unsigned int inlen, const uint8_t *iv, diff --git a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ccm_mode.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ccm_mode.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ccm_mode.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ccm_mode.c index 929adac63..598531252 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ccm_mode.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ccm_mode.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include +#include "../include/tinycrypt/ccm_mode.h" +#include "../include/tinycrypt/constants.h" +#include "../include/tinycrypt/utils.h" #include diff --git a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/cmac_mode.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/cmac_mode.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/cmac_mode.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/cmac_mode.c index 96d147e80..dff28cf03 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/cmac_mode.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/cmac_mode.c @@ -30,10 +30,10 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include -#include +#include "../include/tinycrypt/aes.h" +#include "../include/tinycrypt/cmac_mode.h" +#include "../include/tinycrypt/constants.h" +#include "../include/tinycrypt/utils.h" /* max number of calls until change the key (2^48).*/ const static uint64_t MAX_CALLS = ((uint64_t)1 << 48); diff --git a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_mode.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ctr_mode.c similarity index 95% rename from lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_mode.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ctr_mode.c index 1dfb92dfe..6653afc52 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_mode.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ctr_mode.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include +#include "../include/tinycrypt/constants.h" +#include "../include/tinycrypt/ctr_mode.h" +#include "../include/tinycrypt/utils.h" int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in, unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_prng.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ctr_prng.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_prng.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ctr_prng.c index cac2cc41d..f908932e2 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_prng.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ctr_prng.c @@ -27,9 +27,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include +#include "../include/tinycrypt/ctr_prng.h" +#include "../include/tinycrypt/utils.h" +#include "../include/tinycrypt/constants.h" #include /* diff --git a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc.c index 46080bf61..e7fce278d 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc.c @@ -52,8 +52,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include +#include "../include/tinycrypt/ecc.h" +#include "../include/tinycrypt/ecc_platform_specific.h" #include /* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform diff --git a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dh.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc_dh.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dh.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc_dh.c index e5257d2d4..5cd6a2e2f 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dh.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc_dh.c @@ -54,9 +54,9 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include +#include "../include/tinycrypt/constants.h" +#include "../include/tinycrypt/ecc.h" +#include "../include/tinycrypt/ecc_dh.h" #include #if default_RNG_defined diff --git a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dsa.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc_dsa.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dsa.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc_dsa.c index 064dfe5ae..31046c860 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dsa.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc_dsa.c @@ -53,9 +53,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include +#include "../include/tinycrypt/constants.h" +#include "../include/tinycrypt/ecc.h" +#include "../include/tinycrypt/ecc_dsa.h" #if default_RNG_defined static uECC_RNG_Function g_rng_function = &default_CSPRNG; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_platform_specific.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc_platform_specific.c similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_platform_specific.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc_platform_specific.c diff --git a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/hmac.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/hmac.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/hmac.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/hmac.c index 89878cec7..c86fd35a7 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/hmac.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/hmac.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include +#include "../include/tinycrypt/hmac.h" +#include "../include/tinycrypt/constants.h" +#include "../include/tinycrypt/utils.h" static void rekey(uint8_t *key, const uint8_t *new_key, unsigned int key_size) { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/hmac_prng.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/hmac_prng.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/hmac_prng.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/hmac_prng.c index 68b5b1faf..a41ea43d5 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/hmac_prng.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/hmac_prng.c @@ -30,10 +30,10 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include -#include +#include "../include/tinycrypt/hmac_prng.h" +#include "../include/tinycrypt/hmac.h" +#include "../include/tinycrypt/constants.h" +#include "../include/tinycrypt/utils.h" /* * min bytes in the seed string. diff --git a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/sha256.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/sha256.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/sha256.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/sha256.c index b4efd2044..b7e0bba55 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/sha256.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/sha256.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include +#include "../include/tinycrypt/sha256.h" +#include "../include/tinycrypt/constants.h" +#include "../include/tinycrypt/utils.h" static void compress(unsigned int *iv, const uint8_t *data); diff --git a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/utils.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/utils.c similarity index 96% rename from lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/utils.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/utils.c index 13cc49512..792a78178 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/ext/tinycrypt/src/utils.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/utils.c @@ -30,8 +30,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include +#include "../include/tinycrypt/utils.h" +#include "../include/tinycrypt/constants.h" #include diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_att_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_att_priv.h deleted file mode 100644 index 2201d4ddb..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_att_priv.h +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_ATT_PRIV_ -#define H_BLE_ATT_PRIV_ - -#include -#include "stats/stats.h" -#include "host/ble_att.h" -#include "host/ble_uuid.h" -#include "nimble/nimble_npl.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct os_mbuf; -struct ble_hs_conn; -struct ble_l2cap_chan; -struct ble_att_find_info_req; -struct ble_att_error_rsp; -struct ble_att_mtu_cmd; -struct ble_att_read_req; -struct ble_att_read_blob_req; -struct ble_att_read_type_req; -struct ble_att_read_group_type_req; -struct ble_att_read_group_type_rsp; -struct ble_att_find_type_value_req; -struct ble_att_write_req; -struct ble_att_prep_write_cmd; -struct ble_att_exec_write_req; -struct ble_att_notify_req; -struct ble_att_indicate_req; - -STATS_SECT_START(ble_att_stats) - STATS_SECT_ENTRY(error_rsp_rx) - STATS_SECT_ENTRY(error_rsp_tx) - STATS_SECT_ENTRY(mtu_req_rx) - STATS_SECT_ENTRY(mtu_req_tx) - STATS_SECT_ENTRY(mtu_rsp_rx) - STATS_SECT_ENTRY(mtu_rsp_tx) - STATS_SECT_ENTRY(find_info_req_rx) - STATS_SECT_ENTRY(find_info_req_tx) - STATS_SECT_ENTRY(find_info_rsp_rx) - STATS_SECT_ENTRY(find_info_rsp_tx) - STATS_SECT_ENTRY(find_type_value_req_rx) - STATS_SECT_ENTRY(find_type_value_req_tx) - STATS_SECT_ENTRY(find_type_value_rsp_rx) - STATS_SECT_ENTRY(find_type_value_rsp_tx) - STATS_SECT_ENTRY(read_type_req_rx) - STATS_SECT_ENTRY(read_type_req_tx) - STATS_SECT_ENTRY(read_type_rsp_rx) - STATS_SECT_ENTRY(read_type_rsp_tx) - STATS_SECT_ENTRY(read_req_rx) - STATS_SECT_ENTRY(read_req_tx) - STATS_SECT_ENTRY(read_rsp_rx) - STATS_SECT_ENTRY(read_rsp_tx) - STATS_SECT_ENTRY(read_blob_req_rx) - STATS_SECT_ENTRY(read_blob_req_tx) - STATS_SECT_ENTRY(read_blob_rsp_rx) - STATS_SECT_ENTRY(read_blob_rsp_tx) - STATS_SECT_ENTRY(read_mult_req_rx) - STATS_SECT_ENTRY(read_mult_req_tx) - STATS_SECT_ENTRY(read_mult_rsp_rx) - STATS_SECT_ENTRY(read_mult_rsp_tx) - STATS_SECT_ENTRY(read_group_type_req_rx) - STATS_SECT_ENTRY(read_group_type_req_tx) - STATS_SECT_ENTRY(read_group_type_rsp_rx) - STATS_SECT_ENTRY(read_group_type_rsp_tx) - STATS_SECT_ENTRY(write_req_rx) - STATS_SECT_ENTRY(write_req_tx) - STATS_SECT_ENTRY(write_rsp_rx) - STATS_SECT_ENTRY(write_rsp_tx) - STATS_SECT_ENTRY(prep_write_req_rx) - STATS_SECT_ENTRY(prep_write_req_tx) - STATS_SECT_ENTRY(prep_write_rsp_rx) - STATS_SECT_ENTRY(prep_write_rsp_tx) - STATS_SECT_ENTRY(exec_write_req_rx) - STATS_SECT_ENTRY(exec_write_req_tx) - STATS_SECT_ENTRY(exec_write_rsp_rx) - STATS_SECT_ENTRY(exec_write_rsp_tx) - STATS_SECT_ENTRY(notify_req_rx) - STATS_SECT_ENTRY(notify_req_tx) - STATS_SECT_ENTRY(indicate_req_rx) - STATS_SECT_ENTRY(indicate_req_tx) - STATS_SECT_ENTRY(indicate_rsp_rx) - STATS_SECT_ENTRY(indicate_rsp_tx) - STATS_SECT_ENTRY(write_cmd_rx) - STATS_SECT_ENTRY(write_cmd_tx) -STATS_SECT_END -extern STATS_SECT_DECL(ble_att_stats) ble_att_stats; - -struct ble_att_prep_entry { - SLIST_ENTRY(ble_att_prep_entry) bape_next; - uint16_t bape_handle; - uint16_t bape_offset; - - /* XXX: This is wasteful; we should use one mbuf chain for the entire - * prepared write, and compress the data into as few mbufs as possible. - */ - struct os_mbuf *bape_value; -}; - -SLIST_HEAD(ble_att_prep_entry_list, ble_att_prep_entry); - -struct ble_att_svr_conn { - /** This list is sorted by attribute handle ID. */ - struct ble_att_prep_entry_list basc_prep_list; - ble_npl_time_t basc_prep_timeout_at; -}; - -/** - * Handles a host attribute request. - * - * @param entry The host attribute being requested. - * @param op The operation being performed on the attribute. - * @param arg The request data associated with that host - * attribute. - * - * @return 0 on success; - * One of the BLE_ATT_ERR_[...] codes on - * failure. - */ -typedef int ble_att_svr_access_fn(uint16_t conn_handle, uint16_t attr_handle, - uint8_t op, uint16_t offset, - struct os_mbuf **om, void *arg); - -int ble_att_svr_register(const ble_uuid_t *uuid, uint8_t flags, - uint8_t min_key_size, uint16_t *handle_id, - ble_att_svr_access_fn *cb, void *cb_arg); - -struct ble_att_svr_entry { - STAILQ_ENTRY(ble_att_svr_entry) ha_next; - - const ble_uuid_t *ha_uuid; - uint8_t ha_flags; - uint8_t ha_min_key_size; - uint16_t ha_handle_id; - ble_att_svr_access_fn *ha_cb; - void *ha_cb_arg; -}; - -SLIST_HEAD(ble_att_clt_entry_list, ble_att_clt_entry); - -/*** @gen */ - -struct ble_l2cap_chan *ble_att_create_chan(uint16_t conn_handle); -int ble_att_conn_chan_find(uint16_t conn_handle, struct ble_hs_conn **out_conn, - struct ble_l2cap_chan **out_chan); -void ble_att_inc_tx_stat(uint8_t att_op); -void ble_att_truncate_to_mtu(const struct ble_l2cap_chan *att_chan, - struct os_mbuf *txom); -void ble_att_set_peer_mtu(struct ble_l2cap_chan *chan, uint16_t peer_mtu); -uint16_t ble_att_chan_mtu(const struct ble_l2cap_chan *chan); -int ble_att_init(void); - -#define BLE_ATT_LOG_CMD(is_tx, cmd_name, conn_handle, log_cb, cmd) \ - BLE_HS_LOG_CMD((is_tx), "att", (cmd_name), (conn_handle), (log_cb), (cmd)) - -#define BLE_ATT_LOG_EMPTY_CMD(is_tx, cmd_name, conn_handle) \ - BLE_HS_LOG_EMPTY_CMD((is_tx), "att", (cmd_name), (conn_handle)) - -/*** @svr */ - -int ble_att_svr_start(void); -void ble_att_svr_stop(void); - -struct ble_att_svr_entry * -ble_att_svr_find_by_uuid(struct ble_att_svr_entry *start_at, - const ble_uuid_t *uuid, - uint16_t end_handle); -uint16_t ble_att_svr_prev_handle(void); -int ble_att_svr_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom); -struct ble_att_svr_entry *ble_att_svr_find_by_handle(uint16_t handle_id); -int32_t ble_att_svr_ticks_until_tmo(const struct ble_att_svr_conn *svr, - ble_npl_time_t now); -int ble_att_svr_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_svr_rx_find_type_value(uint16_t conn_handle, - struct os_mbuf **rxom); -int ble_att_svr_rx_read_type(uint16_t conn_handle, - struct os_mbuf **rxom); -int ble_att_svr_rx_read_group_type(uint16_t conn_handle, - struct os_mbuf **rxom); -int ble_att_svr_rx_read(uint16_t conn_handle, - struct os_mbuf **rxom); -int ble_att_svr_rx_read_blob(uint16_t conn_handle, - struct os_mbuf **rxom); -int ble_att_svr_rx_read_mult(uint16_t conn_handle, - struct os_mbuf **rxom); -int ble_att_svr_rx_write(uint16_t conn_handle, - struct os_mbuf **rxom); -int ble_att_svr_rx_write_no_rsp(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_svr_rx_prep_write(uint16_t conn_handle, - struct os_mbuf **rxom); -int ble_att_svr_rx_exec_write(uint16_t conn_handle, - struct os_mbuf **rxom); -int ble_att_svr_rx_notify(uint16_t conn_handle, - struct os_mbuf **rxom); -int ble_att_svr_rx_indicate(uint16_t conn_handle, - struct os_mbuf **rxom); -void ble_att_svr_prep_clear(struct ble_att_prep_entry_list *prep_list); -int ble_att_svr_read_handle(uint16_t conn_handle, uint16_t attr_handle, - uint16_t offset, struct os_mbuf *om, - uint8_t *out_att_err); -void ble_att_svr_reset(void); -int ble_att_svr_init(void); - -void ble_att_svr_hide_range(uint16_t start_handle, uint16_t end_handle); -void ble_att_svr_restore_range(uint16_t start_handle, uint16_t end_handle); - -int ble_att_svr_tx_error_rsp(uint16_t conn_handle, struct os_mbuf *txom, - uint8_t req_op, uint16_t handle, - uint8_t error_code); -/*** $clt */ - -/** An information-data entry in a find information response. */ -struct ble_att_find_info_idata { - uint16_t attr_handle; - ble_uuid_any_t uuid; -}; - -/** A handles-information entry in a find by type value response. */ -struct ble_att_find_type_value_hinfo { - uint16_t attr_handle; - uint16_t group_end_handle; -}; - -/** An attribute-data entry in a read by type response. */ -struct ble_att_read_type_adata { - uint16_t att_handle; - int value_len; - uint8_t *value; - -}; - -/** An attribute-data entry in a read by group type response. */ -struct ble_att_read_group_type_adata { - uint16_t att_handle; - uint16_t end_group_handle; - int value_len; - uint8_t *value; -}; - -int ble_att_clt_rx_error(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_mtu(uint16_t conn_handle, uint16_t mtu); -int ble_att_clt_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_read(uint16_t conn_handle, uint16_t handle); -int ble_att_clt_rx_read(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_read_blob(uint16_t conn_handle, uint16_t handle, - uint16_t offset); -int ble_att_clt_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_read_mult(uint16_t conn_handle, - const uint16_t *handles, int num_handles); -int ble_att_clt_rx_read_mult(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_read_type(uint16_t conn_handle, uint16_t start_handle, - uint16_t end_handle, const ble_uuid_t *uuid); -int ble_att_clt_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_read_group_type(uint16_t conn_handle, - uint16_t start_handle, uint16_t end_handle, - const ble_uuid_t *uuid128); -int ble_att_clt_rx_read_group_type(uint16_t conn_handle, - struct os_mbuf **rxom); -int ble_att_clt_tx_find_info(uint16_t conn_handle, uint16_t start_handle, - uint16_t end_handle); -int ble_att_clt_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_find_type_value(uint16_t conn_handle, uint16_t start_handle, - uint16_t end_handle, uint16_t attribute_type, - const void *attribute_value, int value_len); -int ble_att_clt_rx_find_type_value(uint16_t conn_handle, - struct os_mbuf **rxom); -int ble_att_clt_tx_write_req(uint16_t conn_handle, uint16_t handle, - struct os_mbuf *txom); -int ble_att_clt_tx_write_cmd(uint16_t conn_handle, uint16_t handle, - struct os_mbuf *txom); -int ble_att_clt_tx_prep_write(uint16_t conn_handle, uint16_t handle, - uint16_t offset, struct os_mbuf *txom); -int ble_att_clt_rx_prep_write(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_exec_write(uint16_t conn_handle, uint8_t flags); -int ble_att_clt_rx_exec_write(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_rx_write(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_notify(uint16_t conn_handle, uint16_t handle, - struct os_mbuf *txom); -int ble_att_clt_tx_indicate(uint16_t conn_handle, uint16_t handle, - struct os_mbuf *txom); -int ble_att_clt_rx_indicate(uint16_t conn_handle, struct os_mbuf **rxom); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_hs_conn_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_hs_conn_priv.h deleted file mode 100644 index 92aacd405..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_hs_conn_priv.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_HS_CONN_ -#define H_BLE_HS_CONN_ - -#include -#include "ble_l2cap_priv.h" -#include "ble_gatt_priv.h" -#include "ble_att_priv.h" -#ifdef __cplusplus -extern "C" { -#endif - -struct hci_le_conn_complete; -struct hci_create_conn; -struct ble_l2cap_chan; - -typedef uint8_t ble_hs_conn_flags_t; - -#define BLE_HS_CONN_F_MASTER 0x01 -#define BLE_HS_CONN_F_TERMINATING 0x02 -#define BLE_HS_CONN_F_TX_FRAG 0x04 /* Cur ACL packet partially txed. */ - -struct ble_hs_conn { - SLIST_ENTRY(ble_hs_conn) bhc_next; - uint16_t bhc_handle; - uint8_t bhc_our_addr_type; -#if MYNEWT_VAL(BLE_EXT_ADV) - uint8_t bhc_our_rnd_addr[6]; -#endif - ble_addr_t bhc_peer_addr; - ble_addr_t bhc_our_rpa_addr; - ble_addr_t bhc_peer_rpa_addr; - - uint16_t bhc_itvl; - uint16_t bhc_latency; - uint16_t bhc_supervision_timeout; - uint8_t bhc_master_clock_accuracy; - - uint32_t supported_feat; - - ble_hs_conn_flags_t bhc_flags; - - struct ble_l2cap_chan_list bhc_channels; - struct ble_l2cap_chan *bhc_rx_chan; /* Channel rxing current packet. */ - ble_npl_time_t bhc_rx_timeout; - - /** - * Count of packets sent over this connection that the controller has not - * transmitted or flushed yet. - */ - uint16_t bhc_outstanding_pkts; - -#if MYNEWT_VAL(BLE_HS_FLOW_CTRL) - /** - * Count of packets received over this connection that have been processed - * and freed. - */ - uint16_t bhc_completed_pkts; -#endif - - /** Queue of outgoing packets that could not be sent. */ - STAILQ_HEAD(, os_mbuf_pkthdr) bhc_tx_q; - - struct ble_att_svr_conn bhc_att_svr; - struct ble_gatts_conn bhc_gatt_svr; - - struct ble_gap_sec_state bhc_sec_state; - - ble_gap_event_fn *bhc_cb; - void *bhc_cb_arg; -}; - -struct ble_hs_conn_addrs { - ble_addr_t our_id_addr; - ble_addr_t peer_id_addr; - ble_addr_t our_ota_addr; - ble_addr_t peer_ota_addr; -}; - -int ble_hs_conn_can_alloc(void); -struct ble_hs_conn *ble_hs_conn_alloc(uint16_t conn_handle); -void ble_hs_conn_free(struct ble_hs_conn *conn); -void ble_hs_conn_insert(struct ble_hs_conn *conn); -void ble_hs_conn_remove(struct ble_hs_conn *conn); -struct ble_hs_conn *ble_hs_conn_find(uint16_t conn_handle); -struct ble_hs_conn *ble_hs_conn_find_assert(uint16_t conn_handle); -struct ble_hs_conn *ble_hs_conn_find_by_addr(const ble_addr_t *addr); -struct ble_hs_conn *ble_hs_conn_find_by_idx(int idx); -int ble_hs_conn_exists(uint16_t conn_handle); -struct ble_hs_conn *ble_hs_conn_first(void); -struct ble_l2cap_chan *ble_hs_conn_chan_find_by_scid(struct ble_hs_conn *conn, - uint16_t cid); -struct ble_l2cap_chan *ble_hs_conn_chan_find_by_dcid(struct ble_hs_conn *conn, - uint16_t cid); -int ble_hs_conn_chan_insert(struct ble_hs_conn *conn, - struct ble_l2cap_chan *chan); -void -ble_hs_conn_delete_chan(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan); - -void ble_hs_conn_addrs(const struct ble_hs_conn *conn, - struct ble_hs_conn_addrs *addrs); -int32_t ble_hs_conn_timer(void); - -int ble_hs_conn_init(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_coc_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_coc_priv.h deleted file mode 100644 index 0a1a97b77..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_coc_priv.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_L2CAP_COC_PRIV_ -#define H_L2CAP_COC_PRIV_ - -#include -#include "syscfg/syscfg.h" -#include "os/queue.h" -#include "os/os_mbuf.h" -#include "host/ble_l2cap.h" -#include "ble_l2cap_sig_priv.h" -#ifdef __cplusplus -extern "C" { -#endif - -#define BLE_L2CAP_COC_CID_START 0x0040 -#define BLE_L2CAP_COC_CID_END 0x007F - -struct ble_l2cap_chan; - -#define BLE_L2CAP_COC_FLAG_STALLED 0x01 - -struct ble_l2cap_coc_endpoint { - struct os_mbuf *sdu; - uint16_t mtu; - uint16_t credits; - uint16_t data_offset; - uint8_t flags; -}; - -struct ble_l2cap_coc_srv { - STAILQ_ENTRY(ble_l2cap_coc_srv) next; - uint16_t psm; - uint16_t mtu; - ble_l2cap_event_fn *cb; - void *cb_arg; -}; - -#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) != 0 -int ble_l2cap_coc_init(void); -int ble_l2cap_coc_create_server(uint16_t psm, uint16_t mtu, - ble_l2cap_event_fn *cb, void *cb_arg); -int ble_l2cap_coc_create_srv_chan(uint16_t conn_handle, uint16_t psm, - struct ble_l2cap_chan **chan); -struct ble_l2cap_chan * ble_l2cap_coc_chan_alloc(uint16_t conn_handle, - uint16_t psm, uint16_t mtu, - struct os_mbuf *sdu_rx, - ble_l2cap_event_fn *cb, - void *cb_arg); -void ble_l2cap_coc_cleanup_chan(struct ble_l2cap_chan *chan); -void ble_l2cap_coc_le_credits_update(uint16_t conn_handle, uint16_t dcid, - uint16_t credits); -int ble_l2cap_coc_recv_ready(struct ble_l2cap_chan *chan, - struct os_mbuf *sdu_rx); -int ble_l2cap_coc_send(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_tx); -#else -#define ble_l2cap_coc_init() 0 -#define ble_l2cap_coc_create_server(psm, mtu, cb, cb_arg) BLE_HS_ENOTSUP -#define ble_l2cap_coc_recv_ready(chan, sdu_rx) BLE_HS_ENOTSUP -#define ble_l2cap_coc_cleanup_chan(chan) -#define ble_l2cap_coc_send(chan, sdu_tx) BLE_HS_ENOTSUP -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* H_L2CAP_COC_PRIV_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_priv.h deleted file mode 100644 index 640974d2a..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_priv.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_L2CAP_PRIV_ -#define H_L2CAP_PRIV_ - -#include "ble_l2cap_coc_priv.h" -#include "host/ble_l2cap.h" -#include -#include "stats/stats.h" -#include "os/queue.h" -#include "os/os_mbuf.h" -#ifdef __cplusplus -extern "C" { -#endif - -struct ble_hs_conn; -struct hci_data_hdr; - -STATS_SECT_START(ble_l2cap_stats) - STATS_SECT_ENTRY(chan_create) - STATS_SECT_ENTRY(chan_delete) - STATS_SECT_ENTRY(update_init) - STATS_SECT_ENTRY(update_rx) - STATS_SECT_ENTRY(update_fail) - STATS_SECT_ENTRY(proc_timeout) - STATS_SECT_ENTRY(sig_tx) - STATS_SECT_ENTRY(sig_rx) - STATS_SECT_ENTRY(sm_tx) - STATS_SECT_ENTRY(sm_rx) -STATS_SECT_END -extern STATS_SECT_DECL(ble_l2cap_stats) ble_l2cap_stats; - -extern struct os_mempool ble_l2cap_chan_pool; - -/* This is nimble specific; packets sent to the black hole CID do not elicit - * an "invalid CID" response. - */ -#define BLE_L2CAP_CID_BLACK_HOLE 0xffff - -#define BLE_L2CAP_HDR_SZ 4 - -typedef uint8_t ble_l2cap_chan_flags; - -typedef int ble_l2cap_rx_fn(struct ble_l2cap_chan *chan); - -struct ble_l2cap_chan { - SLIST_ENTRY(ble_l2cap_chan) next; - uint16_t conn_handle; - uint16_t dcid; - uint16_t scid; - uint16_t my_mtu; - uint16_t peer_mtu; /* 0 if not exchanged. */ - ble_l2cap_chan_flags flags; - - struct os_mbuf *rx_buf; - uint16_t rx_len; /* Length of current reassembled rx packet. */ - - ble_l2cap_rx_fn *rx_fn; - -#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) != 0 - uint16_t psm; - struct ble_l2cap_coc_endpoint coc_rx; - struct ble_l2cap_coc_endpoint coc_tx; - uint16_t initial_credits; - ble_l2cap_event_fn *cb; - void *cb_arg; -#endif -}; - -struct ble_l2cap_hdr { - uint16_t len; - uint16_t cid; -}; - -typedef int ble_l2cap_tx_fn(struct ble_hs_conn *conn, - struct ble_l2cap_chan *chan); - -#define BLE_L2CAP_CHAN_F_TXED_MTU 0x01 /* We have sent our MTU. */ - -SLIST_HEAD(ble_l2cap_chan_list, ble_l2cap_chan); - -int ble_l2cap_parse_hdr(struct os_mbuf *om, int off, - struct ble_l2cap_hdr *l2cap_hdr); -struct os_mbuf *ble_l2cap_prepend_hdr(struct os_mbuf *om, uint16_t cid, - uint16_t len); - -struct ble_l2cap_chan *ble_l2cap_chan_alloc(uint16_t conn_handle); -void ble_l2cap_chan_free(struct ble_l2cap_chan *chan); - -bool ble_l2cap_is_mtu_req_sent(const struct ble_l2cap_chan *chan); - -int ble_l2cap_rx(struct ble_hs_conn *conn, - struct hci_data_hdr *hci_hdr, - struct os_mbuf *om, - ble_l2cap_rx_fn **out_rx_cb, - int *out_reject_cid); -int ble_l2cap_tx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan, - struct os_mbuf *txom); - -void ble_l2cap_remove_rx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan); - -int ble_l2cap_init(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_sig_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_sig_priv.h deleted file mode 100644 index 1a6fb8293..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_sig_priv.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_L2CAP_SIG_ -#define H_BLE_L2CAP_SIG_ - -#include "syscfg/syscfg.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define BLE_L2CAP_SIG_MTU 100 /* This is our own default. */ - -#define BLE_L2CAP_SIG_HDR_SZ 4 -struct ble_l2cap_sig_hdr { - uint8_t op; - uint8_t identifier; - uint16_t length; - uint8_t data[0]; -} __attribute__((packed)); - -#define BLE_L2CAP_SIG_REJECT_MIN_SZ 2 -struct ble_l2cap_sig_reject { - uint16_t reason; - uint8_t data[0]; -} __attribute__((packed)); - -#define BLE_L2CAP_SIG_UPDATE_REQ_SZ 8 -struct ble_l2cap_sig_update_req { - uint16_t itvl_min; - uint16_t itvl_max; - uint16_t slave_latency; - uint16_t timeout_multiplier; -} __attribute__((packed)); - -#define BLE_L2CAP_SIG_UPDATE_RSP_SZ 2 -struct ble_l2cap_sig_update_rsp { - uint16_t result; -} __attribute__((packed)); - -#define BLE_L2CAP_SIG_UPDATE_RSP_RESULT_ACCEPT 0x0000 -#define BLE_L2CAP_SIG_UPDATE_RSP_RESULT_REJECT 0x0001 - -struct ble_l2cap_sig_le_con_req { - uint16_t psm; - uint16_t scid; - uint16_t mtu; - uint16_t mps; - uint16_t credits; -} __attribute__((packed)); - -struct ble_l2cap_sig_le_con_rsp { - uint16_t dcid; - uint16_t mtu; - uint16_t mps; - uint16_t credits; - uint16_t result; -} __attribute__((packed)); - -struct ble_l2cap_sig_disc_req { - uint16_t dcid; - uint16_t scid; -} __attribute__((packed)); - -struct ble_l2cap_sig_disc_rsp { - uint16_t dcid; - uint16_t scid; -} __attribute__((packed)); - -struct ble_l2cap_sig_le_credits { - uint16_t scid; - uint16_t credits; -} __attribute__((packed)); - -void ble_l2cap_sig_hdr_parse(void *payload, uint16_t len, - struct ble_l2cap_sig_hdr *hdr); -int ble_l2cap_sig_reject_tx(uint16_t conn_handle, - uint8_t id, uint16_t reason, - void *data, int data_len); -int ble_l2cap_sig_reject_invalid_cid_tx(uint16_t conn_handle, uint8_t id, - uint16_t src_cid, uint16_t dst_cid); -int ble_l2cap_sig_tx(uint16_t conn_handle, struct os_mbuf *txom); -void *ble_l2cap_sig_cmd_get(uint8_t opcode, uint8_t id, uint16_t len, - struct os_mbuf **txom); -#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) != 0 -int ble_l2cap_sig_coc_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu, - struct os_mbuf *sdu_rx, - ble_l2cap_event_fn *cb, void *cb_arg); -int ble_l2cap_sig_disconnect(struct ble_l2cap_chan *chan); -int ble_l2cap_sig_le_credits(uint16_t conn_handle, uint16_t scid, - uint16_t credits); -#else -#define ble_l2cap_sig_coc_connect(conn_handle, psm, mtu, sdu_rx, cb, cb_arg) \ - BLE_HS_ENOTSUP -#define ble_l2cap_sig_disconnect(chan) BLE_HS_ENOTSUP -#endif - -void ble_l2cap_sig_conn_broken(uint16_t conn_handle, int reason); -int32_t ble_l2cap_sig_timer(void); -struct ble_l2cap_chan *ble_l2cap_sig_create_chan(uint16_t conn_handle); -int ble_l2cap_sig_init(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_priv.h deleted file mode 100644 index 73b6aeab0..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_priv.h +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_ATT_PRIV_ -#define H_BLE_ATT_PRIV_ - -#include -#include "stats/stats.h" -#include "host/ble_att.h" -#include "host/ble_uuid.h" -#include "nimble/nimble_npl.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct os_mbuf; -struct ble_hs_conn; -struct ble_l2cap_chan; -struct ble_att_find_info_req; -struct ble_att_error_rsp; -struct ble_att_mtu_cmd; -struct ble_att_read_req; -struct ble_att_read_blob_req; -struct ble_att_read_type_req; -struct ble_att_read_group_type_req; -struct ble_att_read_group_type_rsp; -struct ble_att_find_type_value_req; -struct ble_att_write_req; -struct ble_att_prep_write_cmd; -struct ble_att_exec_write_req; -struct ble_att_notify_req; -struct ble_att_indicate_req; - -STATS_SECT_START(ble_att_stats) - STATS_SECT_ENTRY(error_rsp_rx) - STATS_SECT_ENTRY(error_rsp_tx) - STATS_SECT_ENTRY(mtu_req_rx) - STATS_SECT_ENTRY(mtu_req_tx) - STATS_SECT_ENTRY(mtu_rsp_rx) - STATS_SECT_ENTRY(mtu_rsp_tx) - STATS_SECT_ENTRY(find_info_req_rx) - STATS_SECT_ENTRY(find_info_req_tx) - STATS_SECT_ENTRY(find_info_rsp_rx) - STATS_SECT_ENTRY(find_info_rsp_tx) - STATS_SECT_ENTRY(find_type_value_req_rx) - STATS_SECT_ENTRY(find_type_value_req_tx) - STATS_SECT_ENTRY(find_type_value_rsp_rx) - STATS_SECT_ENTRY(find_type_value_rsp_tx) - STATS_SECT_ENTRY(read_type_req_rx) - STATS_SECT_ENTRY(read_type_req_tx) - STATS_SECT_ENTRY(read_type_rsp_rx) - STATS_SECT_ENTRY(read_type_rsp_tx) - STATS_SECT_ENTRY(read_req_rx) - STATS_SECT_ENTRY(read_req_tx) - STATS_SECT_ENTRY(read_rsp_rx) - STATS_SECT_ENTRY(read_rsp_tx) - STATS_SECT_ENTRY(read_blob_req_rx) - STATS_SECT_ENTRY(read_blob_req_tx) - STATS_SECT_ENTRY(read_blob_rsp_rx) - STATS_SECT_ENTRY(read_blob_rsp_tx) - STATS_SECT_ENTRY(read_mult_req_rx) - STATS_SECT_ENTRY(read_mult_req_tx) - STATS_SECT_ENTRY(read_mult_rsp_rx) - STATS_SECT_ENTRY(read_mult_rsp_tx) - STATS_SECT_ENTRY(read_group_type_req_rx) - STATS_SECT_ENTRY(read_group_type_req_tx) - STATS_SECT_ENTRY(read_group_type_rsp_rx) - STATS_SECT_ENTRY(read_group_type_rsp_tx) - STATS_SECT_ENTRY(write_req_rx) - STATS_SECT_ENTRY(write_req_tx) - STATS_SECT_ENTRY(write_rsp_rx) - STATS_SECT_ENTRY(write_rsp_tx) - STATS_SECT_ENTRY(prep_write_req_rx) - STATS_SECT_ENTRY(prep_write_req_tx) - STATS_SECT_ENTRY(prep_write_rsp_rx) - STATS_SECT_ENTRY(prep_write_rsp_tx) - STATS_SECT_ENTRY(exec_write_req_rx) - STATS_SECT_ENTRY(exec_write_req_tx) - STATS_SECT_ENTRY(exec_write_rsp_rx) - STATS_SECT_ENTRY(exec_write_rsp_tx) - STATS_SECT_ENTRY(notify_req_rx) - STATS_SECT_ENTRY(notify_req_tx) - STATS_SECT_ENTRY(indicate_req_rx) - STATS_SECT_ENTRY(indicate_req_tx) - STATS_SECT_ENTRY(indicate_rsp_rx) - STATS_SECT_ENTRY(indicate_rsp_tx) - STATS_SECT_ENTRY(write_cmd_rx) - STATS_SECT_ENTRY(write_cmd_tx) -STATS_SECT_END -extern STATS_SECT_DECL(ble_att_stats) ble_att_stats; - -struct ble_att_prep_entry { - SLIST_ENTRY(ble_att_prep_entry) bape_next; - uint16_t bape_handle; - uint16_t bape_offset; - - /* XXX: This is wasteful; we should use one mbuf chain for the entire - * prepared write, and compress the data into as few mbufs as possible. - */ - struct os_mbuf *bape_value; -}; - -SLIST_HEAD(ble_att_prep_entry_list, ble_att_prep_entry); - -struct ble_att_svr_conn { - /** This list is sorted by attribute handle ID. */ - struct ble_att_prep_entry_list basc_prep_list; - ble_npl_time_t basc_prep_timeout_at; -}; - -/** - * Handles a host attribute request. - * - * @param entry The host attribute being requested. - * @param op The operation being performed on the attribute. - * @param arg The request data associated with that host - * attribute. - * - * @return 0 on success; - * One of the BLE_ATT_ERR_[...] codes on - * failure. - */ -typedef int ble_att_svr_access_fn(uint16_t conn_handle, uint16_t attr_handle, - uint8_t op, uint16_t offset, - struct os_mbuf **om, void *arg); - -int ble_att_svr_register(const ble_uuid_t *uuid, uint8_t flags, - uint8_t min_key_size, uint16_t *handle_id, - ble_att_svr_access_fn *cb, void *cb_arg); - -struct ble_att_svr_entry { - STAILQ_ENTRY(ble_att_svr_entry) ha_next; - - const ble_uuid_t *ha_uuid; - uint8_t ha_flags; - uint8_t ha_min_key_size; - uint16_t ha_handle_id; - ble_att_svr_access_fn *ha_cb; - void *ha_cb_arg; -}; - -SLIST_HEAD(ble_att_clt_entry_list, ble_att_clt_entry); - -/*** @gen */ - -struct ble_l2cap_chan *ble_att_create_chan(uint16_t conn_handle); -int ble_att_conn_chan_find(uint16_t conn_handle, struct ble_hs_conn **out_conn, - struct ble_l2cap_chan **out_chan); -void ble_att_inc_tx_stat(uint8_t att_op); -void ble_att_truncate_to_mtu(const struct ble_l2cap_chan *att_chan, - struct os_mbuf *txom); -void ble_att_set_peer_mtu(struct ble_l2cap_chan *chan, uint16_t peer_mtu); -uint16_t ble_att_chan_mtu(const struct ble_l2cap_chan *chan); -int ble_att_init(void); - -/*** @svr */ - -int ble_att_svr_start(void); -void ble_att_svr_stop(void); - -struct ble_att_svr_entry * -ble_att_svr_find_by_uuid(struct ble_att_svr_entry *start_at, - const ble_uuid_t *uuid, - uint16_t end_handle); -uint16_t ble_att_svr_prev_handle(void); -int ble_att_svr_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom); -struct ble_att_svr_entry *ble_att_svr_find_by_handle(uint16_t handle_id); -int32_t ble_att_svr_ticks_until_tmo(const struct ble_att_svr_conn *svr, - ble_npl_time_t now); -int ble_att_svr_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_svr_rx_find_type_value(uint16_t conn_handle, - struct os_mbuf **rxom); -int ble_att_svr_rx_read_type(uint16_t conn_handle, - struct os_mbuf **rxom); -int ble_att_svr_rx_read_group_type(uint16_t conn_handle, - struct os_mbuf **rxom); -int ble_att_svr_rx_read(uint16_t conn_handle, - struct os_mbuf **rxom); -int ble_att_svr_rx_read_blob(uint16_t conn_handle, - struct os_mbuf **rxom); -int ble_att_svr_rx_read_mult(uint16_t conn_handle, - struct os_mbuf **rxom); -int ble_att_svr_rx_write(uint16_t conn_handle, - struct os_mbuf **rxom); -int ble_att_svr_rx_write_no_rsp(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_svr_rx_prep_write(uint16_t conn_handle, - struct os_mbuf **rxom); -int ble_att_svr_rx_exec_write(uint16_t conn_handle, - struct os_mbuf **rxom); -int ble_att_svr_rx_notify(uint16_t conn_handle, - struct os_mbuf **rxom); -int ble_att_svr_rx_indicate(uint16_t conn_handle, - struct os_mbuf **rxom); -void ble_att_svr_prep_clear(struct ble_att_prep_entry_list *prep_list); -int ble_att_svr_read_handle(uint16_t conn_handle, uint16_t attr_handle, - uint16_t offset, struct os_mbuf *om, - uint8_t *out_att_err); -void ble_att_svr_reset(void); -int ble_att_svr_init(void); - -void ble_att_svr_hide_range(uint16_t start_handle, uint16_t end_handle); -void ble_att_svr_restore_range(uint16_t start_handle, uint16_t end_handle); - -int ble_att_svr_tx_error_rsp(uint16_t conn_handle, struct os_mbuf *txom, - uint8_t req_op, uint16_t handle, - uint8_t error_code); -/*** $clt */ - -/** An information-data entry in a find information response. */ -struct ble_att_find_info_idata { - uint16_t attr_handle; - ble_uuid_any_t uuid; -}; - -/** A handles-information entry in a find by type value response. */ -struct ble_att_find_type_value_hinfo { - uint16_t attr_handle; - uint16_t group_end_handle; -}; - -/** An attribute-data entry in a read by type response. */ -struct ble_att_read_type_adata { - uint16_t att_handle; - int value_len; - uint8_t *value; - -}; - -/** An attribute-data entry in a read by group type response. */ -struct ble_att_read_group_type_adata { - uint16_t att_handle; - uint16_t end_group_handle; - int value_len; - uint8_t *value; -}; - -int ble_att_clt_rx_error(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_mtu(uint16_t conn_handle, uint16_t mtu); -int ble_att_clt_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_read(uint16_t conn_handle, uint16_t handle); -int ble_att_clt_rx_read(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_read_blob(uint16_t conn_handle, uint16_t handle, - uint16_t offset); -int ble_att_clt_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_read_mult(uint16_t conn_handle, - const uint16_t *handles, int num_handles); -int ble_att_clt_rx_read_mult(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_read_type(uint16_t conn_handle, uint16_t start_handle, - uint16_t end_handle, const ble_uuid_t *uuid); -int ble_att_clt_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_read_group_type(uint16_t conn_handle, - uint16_t start_handle, uint16_t end_handle, - const ble_uuid_t *uuid128); -int ble_att_clt_rx_read_group_type(uint16_t conn_handle, - struct os_mbuf **rxom); -int ble_att_clt_tx_find_info(uint16_t conn_handle, uint16_t start_handle, - uint16_t end_handle); -int ble_att_clt_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_find_type_value(uint16_t conn_handle, uint16_t start_handle, - uint16_t end_handle, uint16_t attribute_type, - const void *attribute_value, int value_len); -int ble_att_clt_rx_find_type_value(uint16_t conn_handle, - struct os_mbuf **rxom); -int ble_att_clt_tx_write_req(uint16_t conn_handle, uint16_t handle, - struct os_mbuf *txom); -int ble_att_clt_tx_write_cmd(uint16_t conn_handle, uint16_t handle, - struct os_mbuf *txom); -int ble_att_clt_tx_prep_write(uint16_t conn_handle, uint16_t handle, - uint16_t offset, struct os_mbuf *txom); -int ble_att_clt_rx_prep_write(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_exec_write(uint16_t conn_handle, uint8_t flags); -int ble_att_clt_rx_exec_write(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_rx_write(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_notify(uint16_t conn_handle, uint16_t handle, - struct os_mbuf *txom); -int ble_att_clt_tx_indicate(uint16_t conn_handle, uint16_t handle, - struct os_mbuf *txom); -int ble_att_clt_rx_indicate(uint16_t conn_handle, struct os_mbuf **rxom); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gatt_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gatt_priv.h deleted file mode 100644 index 4a59635b8..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gatt_priv.h +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_GATT_PRIV_ -#define H_BLE_GATT_PRIV_ - -#include "syscfg/syscfg.h" -#include "stats/stats.h" -#include "host/ble_gatt.h" -#ifdef __cplusplus -extern "C" { -#endif - -struct ble_att_read_type_adata; -struct ble_att_find_type_value_hinfo; -struct ble_att_find_info_idata; -struct ble_att_read_group_type_adata; -struct ble_att_prep_write_cmd; - -STATS_SECT_START(ble_gattc_stats) - STATS_SECT_ENTRY(mtu) - STATS_SECT_ENTRY(mtu_fail) - STATS_SECT_ENTRY(disc_all_svcs) - STATS_SECT_ENTRY(disc_all_svcs_fail) - STATS_SECT_ENTRY(disc_svc_uuid) - STATS_SECT_ENTRY(disc_svc_uuid_fail) - STATS_SECT_ENTRY(find_inc_svcs) - STATS_SECT_ENTRY(find_inc_svcs_fail) - STATS_SECT_ENTRY(disc_all_chrs) - STATS_SECT_ENTRY(disc_all_chrs_fail) - STATS_SECT_ENTRY(disc_chrs_uuid) - STATS_SECT_ENTRY(disc_chrs_uuid_fail) - STATS_SECT_ENTRY(disc_all_dscs) - STATS_SECT_ENTRY(disc_all_dscs_fail) - STATS_SECT_ENTRY(read) - STATS_SECT_ENTRY(read_fail) - STATS_SECT_ENTRY(read_uuid) - STATS_SECT_ENTRY(read_uuid_fail) - STATS_SECT_ENTRY(read_long) - STATS_SECT_ENTRY(read_long_fail) - STATS_SECT_ENTRY(read_mult) - STATS_SECT_ENTRY(read_mult_fail) - STATS_SECT_ENTRY(write_no_rsp) - STATS_SECT_ENTRY(write_no_rsp_fail) - STATS_SECT_ENTRY(write) - STATS_SECT_ENTRY(write_fail) - STATS_SECT_ENTRY(write_long) - STATS_SECT_ENTRY(write_long_fail) - STATS_SECT_ENTRY(write_reliable) - STATS_SECT_ENTRY(write_reliable_fail) - STATS_SECT_ENTRY(notify) - STATS_SECT_ENTRY(notify_fail) - STATS_SECT_ENTRY(indicate) - STATS_SECT_ENTRY(indicate_fail) - STATS_SECT_ENTRY(proc_timeout) -STATS_SECT_END -extern STATS_SECT_DECL(ble_gattc_stats) ble_gattc_stats; - -STATS_SECT_START(ble_gatts_stats) - STATS_SECT_ENTRY(svcs) - STATS_SECT_ENTRY(chrs) - STATS_SECT_ENTRY(dscs) - STATS_SECT_ENTRY(svc_def_reads) - STATS_SECT_ENTRY(svc_inc_reads) - STATS_SECT_ENTRY(chr_def_reads) - STATS_SECT_ENTRY(chr_val_reads) - STATS_SECT_ENTRY(chr_val_writes) - STATS_SECT_ENTRY(dsc_reads) - STATS_SECT_ENTRY(dsc_writes) -STATS_SECT_END -extern STATS_SECT_DECL(ble_gatts_stats) ble_gatts_stats; - -#define BLE_GATT_CHR_DECL_SZ_16 5 -#define BLE_GATT_CHR_DECL_SZ_128 19 - -typedef uint8_t ble_gatts_conn_flags; - -struct ble_gatts_conn { - struct ble_gatts_clt_cfg *clt_cfgs; - int num_clt_cfgs; - - uint16_t indicate_val_handle; -}; - -/*** @client. */ - -int ble_gattc_locked_by_cur_task(void); -void ble_gatts_indicate_fail_notconn(uint16_t conn_handle); - -void ble_gattc_rx_err(uint16_t conn_handle, uint16_t handle, uint16_t status); -void ble_gattc_rx_mtu(uint16_t conn_handle, int status, uint16_t chan_mtu); -void ble_gattc_rx_read_type_adata(uint16_t conn_handle, - struct ble_att_read_type_adata *adata); -void ble_gattc_rx_read_type_complete(uint16_t conn_handle, int status); -void ble_gattc_rx_read_rsp(uint16_t conn_handle, int status, - struct os_mbuf **rxom); -void ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, int status, - struct os_mbuf **rxom); -void ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, int status, - struct os_mbuf **rxom); -void ble_gattc_rx_read_group_type_adata( - uint16_t conn_handle, struct ble_att_read_group_type_adata *adata); -void ble_gattc_rx_read_group_type_complete(uint16_t conn_handle, int rc); -void ble_gattc_rx_find_type_value_hinfo( - uint16_t conn_handle, struct ble_att_find_type_value_hinfo *hinfo); -void ble_gattc_rx_find_type_value_complete(uint16_t conn_handle, int status); -void ble_gattc_rx_write_rsp(uint16_t conn_handle); -void ble_gattc_rx_prep_write_rsp(uint16_t conn_handle, int status, - uint16_t handle, uint16_t offset, - struct os_mbuf **rxom); -void ble_gattc_rx_exec_write_rsp(uint16_t conn_handle, int status); -void ble_gattc_rx_indicate_rsp(uint16_t conn_handle); -void ble_gattc_rx_find_info_idata(uint16_t conn_handle, - struct ble_att_find_info_idata *idata); -void ble_gattc_rx_find_info_complete(uint16_t conn_handle, int status); -void ble_gattc_connection_txable(uint16_t conn_handle); -void ble_gattc_connection_broken(uint16_t conn_handle); -int32_t ble_gattc_timer(void); - -int ble_gattc_any_jobs(void); -int ble_gattc_init(void); - -/*** @server. */ -#define BLE_GATTS_CLT_CFG_F_NOTIFY 0x0001 -#define BLE_GATTS_CLT_CFG_F_INDICATE 0x0002 -#define BLE_GATTS_CLT_CFG_F_MODIFIED 0x0080 /* Internal only. */ -#define BLE_GATTS_CLT_CFG_F_RESERVED 0xfffc - -#define BLE_GATTS_INC_SVC_LEN_NO_UUID 4 -#define BLE_GATTS_INC_SVC_LEN_UUID 6 - -/** - * Contains counts of resources required by the GATT server. The contents of - * this struct are generally used to populate a configuration struct before - * the host is initialized. - */ -struct ble_gatt_resources { - /** Number of services. */ - uint16_t svcs; - - /** Number of included services. */ - uint16_t incs; - - /** Number of characteristics. */ - uint16_t chrs; - - /** Number of descriptors. */ - uint16_t dscs; - - /** - * Number of client characteristic configuration descriptors. Each of - * these also contributes to the total descriptor count. - */ - uint16_t cccds; - - /** Total number of ATT attributes. */ - uint16_t attrs; -}; - -int ble_gatts_rx_indicate_ack(uint16_t conn_handle, uint16_t chr_val_handle); -int ble_gatts_send_next_indicate(uint16_t conn_handle); -void ble_gatts_tx_notifications(void); -void ble_gatts_bonding_established(uint16_t conn_handle); -void ble_gatts_bonding_restored(uint16_t conn_handle); -void ble_gatts_connection_broken(uint16_t conn_handle); -void ble_gatts_lcl_svc_foreach(ble_gatt_svc_foreach_fn cb, void *arg); -int ble_gatts_register_svcs(const struct ble_gatt_svc_def *svcs, - ble_gatt_register_fn *register_cb, - void *cb_arg); -int ble_gatts_clt_cfg_access(uint16_t conn_handle, uint16_t attr_handle, - uint8_t op, uint16_t offset, struct os_mbuf **om, - void *arg); - -/*** @misc. */ -int ble_gatts_conn_can_alloc(void); -int ble_gatts_conn_init(struct ble_gatts_conn *gatts_conn); -int ble_gatts_init(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_hci_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_hci_priv.h deleted file mode 100644 index 362f12cbd..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_hci_priv.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_HS_HCI_PRIV_ -#define H_BLE_HS_HCI_PRIV_ - -#include "nimble/hci_common.h" -#ifdef __cplusplus -extern "C" { -#endif - -struct ble_hs_conn; -struct os_mbuf; - -#define BLE_HS_HCI_LE_FEAT_ENCRYPTION (0x00000001) -#define BLE_HS_HCI_LE_FEAT_CONN_PARAM_REQUEST (0x00000002) -#define BLE_HS_HCI_LE_FEAT_EXT_REJECT (0x00000004) -#define BLE_HS_HCI_LE_FEAT_SLAVE_FEAT_EXCHANGE (0x00000008) -#define BLE_HS_HCI_LE_FEAT_PING (0x00000010) -#define BLE_HS_HCI_LE_FEAT_DATA_PACKET_LENGTH_EXT (0x00000020) -#define BLE_HS_HCI_LE_FEAT_LL_PRIVACY (0x00000040) -#define BLE_HS_HCI_LE_FEAT_EXT_SCANNER_FILTER_POLICIES (0x00000080) -#define BLE_HS_HCI_LE_FEAT_2M_PHY (0x00000100) -#define BLE_HS_HCI_LE_FEAT_STABLE_MOD_INDEX_TX (0x00000200) -#define BLE_HS_HCI_LE_FEAT_STABLE_MOD_INDEX_RX (0x00000400) -#define BLE_HS_HCI_LE_FEAT_CODED_PHY (0x00000800) -#define BLE_HS_HCI_LE_FEAT_EXT_ADV (0x00001000) -#define BLE_HS_HCI_LE_FEAT_PERIODIC_ADV (0x00002000) -#define BLE_HS_HCI_LE_FEAT_CSA2 (0x00004000) -#define BLE_HS_HCI_LE_FEAT_POWER_CLASS_1 (0x00008000) -#define BLE_HS_HCI_LE_FEAT_MIN_NUM_USED_CHAN (0x00010000) - -struct ble_hs_hci_ack { - int bha_status; /* A BLE_HS_E<...> error; NOT a naked HCI code. */ - const uint8_t *bha_params; - int bha_params_len; - uint16_t bha_opcode; - uint8_t bha_hci_handle; -}; - -#if MYNEWT_VAL(BLE_EXT_ADV) -struct ble_hs_hci_ext_scan_param { - uint8_t scan_type; - uint16_t scan_itvl; - uint16_t scan_window; -}; - -struct ble_hs_hci_ext_conn_params { - uint16_t scan_itvl; - uint16_t scan_window; - uint16_t conn_itvl; - uint16_t conn_windows; -}; - -#if MYNEWT_VAL(BLE_PERIODIC_ADV) -/* Periodic Advertising Parameters */ -struct hci_periodic_adv_params -{ - uint16_t min_interval; - uint16_t max_interval; - uint16_t properties; -}; -#endif -#endif - -extern uint16_t ble_hs_hci_avail_pkts; - -int ble_hs_hci_cmd_tx(uint16_t opcode, const void *cmd, uint8_t cmd_len, - void *rsp, uint8_t rsp_len); -void ble_hs_hci_init(void); -void ble_hs_hci_deinit(void); - -void ble_hs_hci_set_le_supported_feat(uint32_t feat); -uint32_t ble_hs_hci_get_le_supported_feat(void); -void ble_hs_hci_set_hci_version(uint8_t hci_version); -uint8_t ble_hs_hci_get_hci_version(void); - -#if MYNEWT_VAL(BLE_HS_PHONY_HCI_ACKS) -typedef int ble_hs_hci_phony_ack_fn(uint8_t *ack, int ack_buf_len); -void ble_hs_hci_set_phony_ack_cb(ble_hs_hci_phony_ack_fn *cb); -#endif - -int ble_hs_hci_util_read_adv_tx_pwr(int8_t *out_pwr); -int ble_hs_hci_util_rand(void *dst, int len); -int ble_hs_hci_util_read_rssi(uint16_t conn_handle, int8_t *out_rssi); -int ble_hs_hci_util_set_random_addr(const uint8_t *addr); -int ble_hs_hci_util_data_hdr_strip(struct os_mbuf *om, - struct hci_data_hdr *out_hdr); -int ble_hs_hci_evt_process(const struct ble_hci_ev *ev); - -int ble_hs_hci_cmd_send_buf(uint16_t opcode, const void *buf, uint8_t buf_len); -int ble_hs_hci_set_buf_sz(uint16_t pktlen, uint16_t max_pkts); -void ble_hs_hci_add_avail_pkts(uint16_t delta); - -uint16_t ble_hs_hci_util_handle_pb_bc_join(uint16_t handle, uint8_t pb, - uint8_t bc); - -int ble_hs_hci_acl_tx_now(struct ble_hs_conn *conn, struct os_mbuf **om); -int ble_hs_hci_acl_tx(struct ble_hs_conn *conn, struct os_mbuf **om); - -int ble_hs_hci_frag_num_mbufs(void); -int ble_hs_hci_frag_num_mbufs_free(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_coc_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_coc_priv.h deleted file mode 100644 index 5ebdaa050..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_coc_priv.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_L2CAP_COC_PRIV_ -#define H_L2CAP_COC_PRIV_ - -#include -#include "syscfg/syscfg.h" -#include "os/queue.h" -#include "os/os_mbuf.h" -#include "host/ble_l2cap.h" -#include "ble_l2cap_sig_priv.h" -#ifdef __cplusplus -extern "C" { -#endif - -#define BLE_L2CAP_COC_CID_START 0x0040 -#define BLE_L2CAP_COC_CID_END 0x007F - -struct ble_l2cap_chan; - -#define BLE_L2CAP_COC_FLAG_STALLED 0x01 - -struct ble_l2cap_coc_endpoint { - struct os_mbuf *sdu; - uint16_t mtu; - uint16_t credits; - uint16_t data_offset; - uint8_t flags; -}; - -struct ble_l2cap_coc_srv { - STAILQ_ENTRY(ble_l2cap_coc_srv) next; - uint16_t psm; - uint16_t mtu; - ble_l2cap_event_fn *cb; - void *cb_arg; -}; - -#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) != 0 -int ble_l2cap_coc_init(void); -int ble_l2cap_coc_create_server(uint16_t psm, uint16_t mtu, - ble_l2cap_event_fn *cb, void *cb_arg); -int ble_l2cap_coc_create_srv_chan(struct ble_hs_conn *conn, uint16_t psm, - struct ble_l2cap_chan **chan); -struct ble_l2cap_chan * ble_l2cap_coc_chan_alloc(struct ble_hs_conn *conn, - uint16_t psm, uint16_t mtu, - struct os_mbuf *sdu_rx, - ble_l2cap_event_fn *cb, - void *cb_arg); -void ble_l2cap_coc_cleanup_chan(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan); -void ble_l2cap_coc_le_credits_update(uint16_t conn_handle, uint16_t dcid, - uint16_t credits); -int ble_l2cap_coc_recv_ready(struct ble_l2cap_chan *chan, - struct os_mbuf *sdu_rx); -int ble_l2cap_coc_send(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_tx); -void ble_l2cap_coc_set_new_mtu_mps(struct ble_l2cap_chan *chan, uint16_t mtu, uint16_t mps); -#else -static inline int -ble_l2cap_coc_init(void) { - return 0; -} - -static inline int -ble_l2cap_coc_create_server(uint16_t psm, uint16_t mtu, - ble_l2cap_event_fn *cb, void *cb_arg) { - return BLE_HS_ENOTSUP; -} - -static inline int -ble_l2cap_coc_recv_ready(struct ble_l2cap_chan *chan, - struct os_mbuf *sdu_rx) { - return BLE_HS_ENOTSUP; -} - -static inline void -ble_l2cap_coc_cleanup_chan(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan) { -} - -static inline int -ble_l2cap_coc_send(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_tx) { - return BLE_HS_ENOTSUP; -} -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* H_L2CAP_COC_PRIV_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_priv.h deleted file mode 100644 index e3409743b..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_priv.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_L2CAP_PRIV_ -#define H_L2CAP_PRIV_ - -#include "ble_l2cap_coc_priv.h" -#include "host/ble_l2cap.h" -#include -#include "stats/stats.h" -#include "os/queue.h" -#include "os/os_mbuf.h" -#ifdef __cplusplus -extern "C" { -#endif - -struct ble_hs_conn; -struct hci_data_hdr; - -STATS_SECT_START(ble_l2cap_stats) - STATS_SECT_ENTRY(chan_create) - STATS_SECT_ENTRY(chan_delete) - STATS_SECT_ENTRY(update_init) - STATS_SECT_ENTRY(update_rx) - STATS_SECT_ENTRY(update_fail) - STATS_SECT_ENTRY(proc_timeout) - STATS_SECT_ENTRY(sig_tx) - STATS_SECT_ENTRY(sig_rx) - STATS_SECT_ENTRY(sm_tx) - STATS_SECT_ENTRY(sm_rx) -STATS_SECT_END -extern STATS_SECT_DECL(ble_l2cap_stats) ble_l2cap_stats; - -extern struct os_mempool ble_l2cap_chan_pool; - -/* This is nimble specific; packets sent to the black hole CID do not elicit - * an "invalid CID" response. - */ -#define BLE_L2CAP_CID_BLACK_HOLE 0xffff - -#define BLE_L2CAP_HDR_SZ 4 - -typedef uint8_t ble_l2cap_chan_flags; - -typedef int ble_l2cap_rx_fn(struct ble_l2cap_chan *chan); - -struct ble_l2cap_chan { - SLIST_ENTRY(ble_l2cap_chan) next; - uint16_t conn_handle; - uint16_t dcid; - uint16_t scid; - - /* Unions just to avoid confusion on MPS/MTU. - * In CoC context, L2CAP MTU is MPS - */ - union { - uint16_t my_mtu; - uint16_t my_coc_mps; - }; - - union { - uint16_t peer_mtu; - uint16_t peer_coc_mps; - }; - - ble_l2cap_chan_flags flags; - - struct os_mbuf *rx_buf; - uint16_t rx_len; /* Length of current reassembled rx packet. */ - - ble_l2cap_rx_fn *rx_fn; - -#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) != 0 - uint16_t psm; - struct ble_l2cap_coc_endpoint coc_rx; - struct ble_l2cap_coc_endpoint coc_tx; - uint16_t initial_credits; - ble_l2cap_event_fn *cb; - void *cb_arg; -#endif -}; - -struct ble_l2cap_hdr { - uint16_t len; - uint16_t cid; -}; - -typedef int ble_l2cap_tx_fn(struct ble_hs_conn *conn, - struct ble_l2cap_chan *chan); - -#define BLE_L2CAP_CHAN_F_TXED_MTU 0x01 /* We have sent our MTU. */ - -SLIST_HEAD(ble_l2cap_chan_list, ble_l2cap_chan); - -int ble_l2cap_parse_hdr(struct os_mbuf *om, int off, - struct ble_l2cap_hdr *l2cap_hdr); -struct os_mbuf *ble_l2cap_prepend_hdr(struct os_mbuf *om, uint16_t cid, - uint16_t len); - -struct ble_l2cap_chan *ble_l2cap_chan_alloc(uint16_t conn_handle); -void ble_l2cap_chan_free(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan); - -bool ble_l2cap_is_mtu_req_sent(const struct ble_l2cap_chan *chan); - -int ble_l2cap_rx(struct ble_hs_conn *conn, - struct hci_data_hdr *hci_hdr, - struct os_mbuf *om, - ble_l2cap_rx_fn **out_rx_cb, - int *out_reject_cid); -int ble_l2cap_tx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan, - struct os_mbuf *txom); - -void ble_l2cap_remove_rx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan); - -int ble_l2cap_init(void); - -/* Below experimental API is available when BLE_VERSION >= 52 */ -int ble_l2cap_enhanced_connect(uint16_t conn_handle, - uint16_t psm, uint16_t mtu, - uint8_t num, struct os_mbuf *sdu_rx[], - ble_l2cap_event_fn *cb, void *cb_arg); -int ble_l2cap_reconfig(struct ble_l2cap_chan *chans[], uint8_t num, uint16_t new_mtu); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_sig_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_sig_priv.h deleted file mode 100644 index a698cd0d8..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_sig_priv.h +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_L2CAP_SIG_ -#define H_BLE_L2CAP_SIG_ - -#include "syscfg/syscfg.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define BLE_L2CAP_SIG_MTU 100 /* This is our own default. */ - -#define BLE_L2CAP_SIG_HDR_SZ 4 -struct ble_l2cap_sig_hdr { - uint8_t op; - uint8_t identifier; - uint16_t length; - uint8_t data[0]; -} __attribute__((packed)); - -#define BLE_L2CAP_SIG_REJECT_MIN_SZ 2 -struct ble_l2cap_sig_reject { - uint16_t reason; - uint8_t data[0]; -} __attribute__((packed)); - -#define BLE_L2CAP_SIG_UPDATE_REQ_SZ 8 -struct ble_l2cap_sig_update_req { - uint16_t itvl_min; - uint16_t itvl_max; - uint16_t slave_latency; - uint16_t timeout_multiplier; -} __attribute__((packed)); - -#define BLE_L2CAP_SIG_UPDATE_RSP_SZ 2 -struct ble_l2cap_sig_update_rsp { - uint16_t result; -} __attribute__((packed)); - -#define BLE_L2CAP_SIG_UPDATE_RSP_RESULT_ACCEPT 0x0000 -#define BLE_L2CAP_SIG_UPDATE_RSP_RESULT_REJECT 0x0001 - -struct ble_l2cap_sig_le_con_req { - uint16_t psm; - uint16_t scid; - uint16_t mtu; - uint16_t mps; - uint16_t credits; -} __attribute__((packed)); - -struct ble_l2cap_sig_le_con_rsp { - uint16_t dcid; - uint16_t mtu; - uint16_t mps; - uint16_t credits; - uint16_t result; -} __attribute__((packed)); - -struct ble_l2cap_sig_credit_base_connect_req { - uint16_t psm; - uint16_t mtu; - uint16_t mps; - uint16_t credits; - uint16_t scids[0]; -} __attribute__((packed)); - -struct ble_l2cap_sig_credit_base_connect_rsp { - uint16_t mtu; - uint16_t mps; - uint16_t credits; - uint16_t result; - uint16_t dcids[0]; -} __attribute__((packed)); - -struct ble_l2cap_sig_credit_base_reconfig_req { - uint16_t mtu; - uint16_t mps; - uint16_t dcids[0]; -} __attribute__((packed)); - -struct ble_l2cap_sig_credit_base_reconfig_rsp { - uint16_t result; -} __attribute__((packed)); - -struct ble_l2cap_sig_disc_req { - uint16_t dcid; - uint16_t scid; -} __attribute__((packed)); - -struct ble_l2cap_sig_disc_rsp { - uint16_t dcid; - uint16_t scid; -} __attribute__((packed)); - -struct ble_l2cap_sig_le_credits { - uint16_t scid; - uint16_t credits; -} __attribute__((packed)); - -void ble_l2cap_sig_hdr_parse(void *payload, uint16_t len, - struct ble_l2cap_sig_hdr *hdr); -int ble_l2cap_sig_reject_tx(uint16_t conn_handle, - uint8_t id, uint16_t reason, - void *data, int data_len); -int ble_l2cap_sig_reject_invalid_cid_tx(uint16_t conn_handle, uint8_t id, - uint16_t src_cid, uint16_t dst_cid); -int ble_l2cap_sig_tx(uint16_t conn_handle, struct os_mbuf *txom); -void *ble_l2cap_sig_cmd_get(uint8_t opcode, uint8_t id, uint16_t len, - struct os_mbuf **txom); -#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) != 0 -int ble_l2cap_sig_coc_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu, - struct os_mbuf *sdu_rx, - ble_l2cap_event_fn *cb, void *cb_arg); -int ble_l2cap_sig_disconnect(struct ble_l2cap_chan *chan); -int ble_l2cap_sig_le_credits(uint16_t conn_handle, uint16_t scid, - uint16_t credits); -#else -static inline int -ble_l2cap_sig_coc_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu, - struct os_mbuf *sdu_rx, - ble_l2cap_event_fn *cb, void *cb_arg) -{ - return BLE_HS_ENOTSUP; -} - -static inline int -ble_l2cap_sig_disconnect(struct ble_l2cap_chan *chan) -{ - return BLE_HS_ENOTSUP; -} -#endif - -#if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC) -int ble_l2cap_sig_ecoc_connect(uint16_t conn_handle, - uint16_t psm, uint16_t mtu, - uint8_t num, struct os_mbuf *sdu_rx[], - ble_l2cap_event_fn *cb, void *cb_arg); -int ble_l2cap_sig_coc_reconfig(uint16_t conn_handle, struct ble_l2cap_chan *chans[], - uint8_t num, uint16_t new_mtu); -#else -static inline int -ble_l2cap_sig_ecoc_connect(uint16_t conn_handle, - uint16_t psm, uint16_t mtu, - uint8_t num, struct os_mbuf *sdu_rx[], - ble_l2cap_event_fn *cb, void *cb_arg) -{ - return BLE_HS_ENOTSUP; -} -static inline int -ble_l2cap_sig_coc_reconfig(uint16_t conn_handle, struct ble_l2cap_chan *chans[], - uint8_t num, uint16_t new_mtu) -{ - return BLE_HS_ENOTSUP; -} -#endif - -void ble_l2cap_sig_conn_broken(uint16_t conn_handle, int reason); -int32_t ble_l2cap_sig_timer(void); -struct ble_l2cap_chan *ble_l2cap_sig_create_chan(uint16_t conn_handle); -int ble_l2cap_sig_init(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_sm_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_sm_priv.h deleted file mode 100644 index def0a32f5..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_sm_priv.h +++ /dev/null @@ -1,428 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_SM_PRIV_ -#define H_BLE_SM_PRIV_ - -#include -#include "syscfg/syscfg.h" -#include "os/queue.h" -#include "nimble/nimble_opt.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct ble_gap_sec_state; -struct hci_le_lt_key_req; -struct hci_encrypt_change; - -#define BLE_SM_MTU 65 - -#define BLE_SM_OP_PAIR_REQ 0x01 -#define BLE_SM_OP_PAIR_RSP 0x02 -#define BLE_SM_OP_PAIR_CONFIRM 0x03 -#define BLE_SM_OP_PAIR_RANDOM 0x04 -#define BLE_SM_OP_PAIR_FAIL 0x05 -#define BLE_SM_OP_ENC_INFO 0x06 -#define BLE_SM_OP_MASTER_ID 0x07 -#define BLE_SM_OP_IDENTITY_INFO 0x08 -#define BLE_SM_OP_IDENTITY_ADDR_INFO 0x09 -#define BLE_SM_OP_SIGN_INFO 0x0a -#define BLE_SM_OP_SEC_REQ 0x0b -#define BLE_SM_OP_PAIR_PUBLIC_KEY 0x0c -#define BLE_SM_OP_PAIR_DHKEY_CHECK 0x0d -#define BLE_SM_OP_PAIR_KEYPRESS_NOTIFY 0x0e - -struct ble_sm_hdr { - uint8_t opcode; - uint8_t data[0]; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | (Code=0x01/0x02 [req/rsp]) | 1 | - * | IO Capability | 1 | - * | OOB data flag | 1 | - * | AuthReq | 1 | - * | Maximum Encryption Key Size | 1 | - * | Initiator Key Distribution | 1 | - * | Responder Key Distribution | 1 | - */ - -struct ble_sm_pair_cmd { - uint8_t io_cap; - uint8_t oob_data_flag; - uint8_t authreq; - uint8_t max_enc_key_size; - uint8_t init_key_dist; - uint8_t resp_key_dist; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | (Code=0x03) | 1 | - * | Confirm Value | 16 | - */ - -struct ble_sm_pair_confirm { - uint8_t value[16]; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | (Code=0x04) | 1 | - * | Random Value | 16 | - */ -struct ble_sm_pair_random { - uint8_t value[16]; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | (Code=0x05) | 1 | - * | Reason | 1 | - */ -struct ble_sm_pair_fail { - uint8_t reason; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | (Code=0x06) | 1 | - * | ltk | 16 | - */ -struct ble_sm_enc_info { - uint8_t ltk[16]; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | (Code=0x07) | 1 | - * | EDIV | 2 | - * | RAND | 8 | - */ -struct ble_sm_master_id { - uint16_t ediv; - uint64_t rand_val; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | (Code=0x08) | 1 | - * | irk | 16 | - */ -struct ble_sm_id_info { - uint8_t irk[16]; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | (Code=0x09) | 1 | - * | addr_type | 1 | - * | address | 6 | - */ -struct ble_sm_id_addr_info { - uint8_t addr_type; - uint8_t bd_addr[6]; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | (Code=0x0A) | 1 | - * | csrk | 16 | - */ -struct ble_sm_sign_info { - uint8_t sig_key[16]; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | (Code=0x0B) | 1 | - * | authreq | 1 | - */ -struct ble_sm_sec_req { - uint8_t authreq; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | (Code=0x0c) | 1 | - * | Public Key X | 32 | - * | Public Key Y | 32 | - */ -struct ble_sm_public_key { - uint8_t x[32]; - uint8_t y[32]; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | (Code=0x0d) | 1 | - * | DHKey Check | 16 | - */ -struct ble_sm_dhkey_check { - uint8_t value[16]; -} __attribute__((packed)); - -#if NIMBLE_BLE_SM - -#define BLE_SM_PROC_STATE_NONE ((uint8_t)-1) - -#define BLE_SM_PROC_STATE_PAIR 0 -#define BLE_SM_PROC_STATE_CONFIRM 1 -#define BLE_SM_PROC_STATE_RANDOM 2 -#define BLE_SM_PROC_STATE_LTK_START 3 -#define BLE_SM_PROC_STATE_LTK_RESTORE 4 -#define BLE_SM_PROC_STATE_ENC_START 5 -#define BLE_SM_PROC_STATE_ENC_RESTORE 6 -#define BLE_SM_PROC_STATE_KEY_EXCH 7 -#define BLE_SM_PROC_STATE_SEC_REQ 8 -#define BLE_SM_PROC_STATE_PUBLIC_KEY 9 -#define BLE_SM_PROC_STATE_DHKEY_CHECK 10 -#define BLE_SM_PROC_STATE_CNT 11 - -#define BLE_SM_PROC_F_INITIATOR 0x01 -#define BLE_SM_PROC_F_IO_INJECTED 0x02 -#define BLE_SM_PROC_F_ADVANCE_ON_IO 0x04 -#define BLE_SM_PROC_F_AUTHENTICATED 0x08 -#define BLE_SM_PROC_F_SC 0x10 -#define BLE_SM_PROC_F_BONDING 0x20 - -#define BLE_SM_KE_F_ENC_INFO 0x01 -#define BLE_SM_KE_F_MASTER_ID 0x02 -#define BLE_SM_KE_F_ID_INFO 0x04 -#define BLE_SM_KE_F_ADDR_INFO 0x08 -#define BLE_SM_KE_F_SIGN_INFO 0x10 - -typedef uint8_t ble_sm_proc_flags; - -struct ble_sm_keys { - unsigned ltk_valid:1; - unsigned ediv_rand_valid:1; - unsigned irk_valid:1; - unsigned csrk_valid:1; - unsigned addr_valid:1; - uint16_t ediv; - uint64_t rand_val; - uint8_t addr_type; - uint8_t key_size; - uint8_t ltk[16]; /* Little endian. */ - uint8_t irk[16]; /* Little endian. */ - uint8_t csrk[16]; /* Little endian. */ - uint8_t addr[6]; /* Little endian. */ -}; - -struct ble_sm_proc { - STAILQ_ENTRY(ble_sm_proc) next; - - ble_npl_time_t exp_os_ticks; - ble_sm_proc_flags flags; - uint16_t conn_handle; - uint8_t pair_alg; - uint8_t state; - uint8_t rx_key_flags; - uint8_t key_size; - - uint8_t pair_req[sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_pair_cmd)]; - uint8_t pair_rsp[sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_pair_cmd)]; - uint8_t tk[16]; - uint8_t confirm_peer[16]; - uint8_t randm[16]; - uint8_t rands[16]; - uint8_t ltk[16]; /* Little endian. */ - struct ble_sm_keys our_keys; - struct ble_sm_keys peer_keys; - -#if MYNEWT_VAL(BLE_SM_SC) - /* Secure connections. */ - uint8_t passkey_bits_exchanged; - uint8_t ri; - struct ble_sm_public_key pub_key_peer; - uint8_t mackey[16]; - uint8_t dhkey[32]; - const struct ble_sm_sc_oob_data *oob_data_local; - const struct ble_sm_sc_oob_data *oob_data_remote; -#endif -}; - -struct ble_sm_result { - int app_status; - uint8_t sm_err; - struct ble_gap_passkey_params passkey_params; - void *state_arg; - unsigned execute : 1; - unsigned enc_cb : 1; - unsigned bonded : 1; - unsigned restore : 1; -}; - -#if MYNEWT_VAL(BLE_HS_DEBUG) -void ble_sm_dbg_set_next_pair_rand(uint8_t *next_pair_rand); -void ble_sm_dbg_set_next_ediv(uint16_t next_ediv); -void ble_sm_dbg_set_next_master_id_rand(uint64_t next_master_id_rand); -void ble_sm_dbg_set_next_ltk(uint8_t *next_ltk); -void ble_sm_dbg_set_next_csrk(uint8_t *next_csrk); -void ble_sm_dbg_set_sc_keys(uint8_t *pubkey, uint8_t *privkey); -#endif - -int ble_sm_num_procs(void); - -int ble_sm_alg_s1(const uint8_t *k, const uint8_t *r1, const uint8_t *r2, - uint8_t *out); -int ble_sm_alg_c1(const uint8_t *k, const uint8_t *r, - const uint8_t *preq, const uint8_t *pres, - uint8_t iat, uint8_t rat, - const uint8_t *ia, const uint8_t *ra, - uint8_t *out_enc_data); -int ble_sm_alg_f4(const uint8_t *u, const uint8_t *v, const uint8_t *x, - uint8_t z, uint8_t *out_enc_data); -int ble_sm_alg_g2(const uint8_t *u, const uint8_t *v, const uint8_t *x, - const uint8_t *y, uint32_t *passkey); -int ble_sm_alg_f5(const uint8_t *w, const uint8_t *n1, const uint8_t *n2, - uint8_t a1t, const uint8_t *a1, uint8_t a2t, - const uint8_t *a2, uint8_t *mackey, uint8_t *ltk); -int ble_sm_alg_f6(const uint8_t *w, const uint8_t *n1, const uint8_t *n2, - const uint8_t *r, const uint8_t *iocap, uint8_t a1t, - const uint8_t *a1, uint8_t a2t, const uint8_t *a2, - uint8_t *check); -int ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, - const uint8_t *peer_pub_key_y, - const uint8_t *our_priv_key, uint8_t *out_dhkey); -int ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv); -void ble_sm_alg_ecc_init(void); - -void ble_sm_enc_change_rx(const struct ble_hci_ev_enrypt_chg *ev); -void ble_sm_enc_key_refresh_rx(const struct ble_hci_ev_enc_key_refresh *ev); -int ble_sm_ltk_req_rx(const struct ble_hci_ev_le_subev_lt_key_req *ev); - -#if MYNEWT_VAL(BLE_SM_LEGACY) -int ble_sm_lgcy_io_action(struct ble_sm_proc *proc, uint8_t *action); -void ble_sm_lgcy_confirm_exec(struct ble_sm_proc *proc, - struct ble_sm_result *res); -void ble_sm_lgcy_random_exec(struct ble_sm_proc *proc, - struct ble_sm_result *res); -void ble_sm_lgcy_random_rx(struct ble_sm_proc *proc, - struct ble_sm_result *res); -#else -#define ble_sm_lgcy_io_action(proc, action) (BLE_HS_ENOTSUP) -#define ble_sm_lgcy_confirm_exec(proc, res) -#define ble_sm_lgcy_random_exec(proc, res) -#define ble_sm_lgcy_random_rx(proc, res) -#endif - -#if MYNEWT_VAL(BLE_SM_SC) -int ble_sm_sc_io_action(struct ble_sm_proc *proc, uint8_t *action); -void ble_sm_sc_confirm_exec(struct ble_sm_proc *proc, - struct ble_sm_result *res); -void ble_sm_sc_random_exec(struct ble_sm_proc *proc, - struct ble_sm_result *res); -void ble_sm_sc_random_rx(struct ble_sm_proc *proc, struct ble_sm_result *res); -void ble_sm_sc_public_key_exec(struct ble_sm_proc *proc, - struct ble_sm_result *res, - void *arg); -void ble_sm_sc_public_key_rx(uint16_t conn_handle, struct os_mbuf **rxom, - struct ble_sm_result *res); -void ble_sm_sc_dhkey_check_exec(struct ble_sm_proc *proc, - struct ble_sm_result *res, void *arg); -void ble_sm_sc_dhkey_check_rx(uint16_t conn_handle, struct os_mbuf **rxom, - struct ble_sm_result *res); -bool ble_sm_sc_oob_data_check(struct ble_sm_proc *proc, - bool oob_data_local_present, - bool oob_data_remote_present); -void ble_sm_sc_oob_confirm(struct ble_sm_proc *proc, struct ble_sm_result *res); -void ble_sm_sc_init(void); -#else -#define ble_sm_sc_io_action(proc, action) (BLE_HS_ENOTSUP) -#define ble_sm_sc_confirm_exec(proc, res) -#define ble_sm_sc_random_exec(proc, res) -#define ble_sm_sc_random_rx(proc, res) -#define ble_sm_sc_public_key_exec(proc, res, arg) -#define ble_sm_sc_public_key_rx(conn_handle, op, om, res) -#define ble_sm_sc_dhkey_check_exec(proc, res, arg) -#define ble_sm_sc_dhkey_check_rx(conn_handle, op, om, res) -#define ble_sm_sc_init() - -#endif - -struct ble_sm_proc *ble_sm_proc_find(uint16_t conn_handle, uint8_t state, - int is_initiator, - struct ble_sm_proc **out_prev); -int ble_sm_gen_pair_rand(uint8_t *pair_rand); -uint8_t *ble_sm_our_pair_rand(struct ble_sm_proc *proc); -uint8_t *ble_sm_peer_pair_rand(struct ble_sm_proc *proc); -int ble_sm_ioact_state(uint8_t action); -int ble_sm_proc_can_advance(struct ble_sm_proc *proc); -void ble_sm_process_result(uint16_t conn_handle, struct ble_sm_result *res); -void ble_sm_confirm_advance(struct ble_sm_proc *proc); -void ble_sm_ia_ra(struct ble_sm_proc *proc, - uint8_t *out_iat, uint8_t *out_ia, - uint8_t *out_rat, uint8_t *out_ra); - -int32_t ble_sm_timer(void); -void ble_sm_connection_broken(uint16_t conn_handle); -int ble_sm_pair_initiate(uint16_t conn_handle); -int ble_sm_slave_initiate(uint16_t conn_handle); -int ble_sm_enc_initiate(uint16_t conn_handle, uint8_t key_size, - const uint8_t *ltk, uint16_t ediv, - uint64_t rand_val, int auth); -int ble_sm_alg_encrypt(const uint8_t *key, const uint8_t *plaintext, - uint8_t *enc_data); -int ble_sm_init(void); -#else - -#define ble_sm_enc_change_rx(evt) ((void)(evt)) -#define ble_sm_ltk_req_rx(evt) ((void)(evt)) -#define ble_sm_enc_key_refresh_rx(evt) ((void)(evt)) - -#define ble_sm_timer() BLE_HS_FOREVER -#define ble_sm_connection_broken(conn_handle) -#define ble_sm_pair_initiate(conn_handle) BLE_HS_ENOTSUP -#define ble_sm_slave_initiate(conn_handle) BLE_HS_ENOTSUP -#define ble_sm_enc_initiate(conn_handle, keysize, ltk, ediv, rand_val, auth) \ - BLE_HS_ENOTSUP - -#define ble_sm_init() 0 - -#define ble_sm_alg_encrypt(key, plaintext, enc_data) \ - BLE_HS_ENOTSUP - -#endif - -struct ble_l2cap_chan *ble_sm_create_chan(uint16_t handle); -void *ble_sm_cmd_get(uint8_t opcode, size_t len, struct os_mbuf **txom); -int ble_sm_tx(uint16_t conn_handle, struct os_mbuf *txom); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/testing.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/testing.c deleted file mode 100644 index d0a053760..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/testing.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -#include "console/console.h" -#include "mesh/testing.h" -#include "mesh/slist.h" -#include "mesh/glue.h" -#include "mesh/access.h" - -#include "net.h" -#include "testing.h" -#include "access.h" -#include "foundation.h" -#include "lpn.h" -#include "transport.h" - -static sys_slist_t cb_slist; - -void bt_test_cb_register(struct bt_test_cb *cb) -{ - sys_slist_append(&cb_slist, &cb->node); -} - -void bt_test_cb_unregister(struct bt_test_cb *cb) -{ - sys_slist_find_and_remove(&cb_slist, &cb->node); -} - -void bt_test_mesh_net_recv(u8_t ttl, u8_t ctl, u16_t src, u16_t dst, - const void *payload, size_t payload_len) -{ - struct bt_test_cb *cb; - - SYS_SLIST_FOR_EACH_CONTAINER(&cb_slist, cb, node) { - if (cb->mesh_net_recv) { - cb->mesh_net_recv(ttl, ctl, src, dst, payload, - payload_len); - } - } -} - -void bt_test_mesh_model_bound(u16_t addr, struct bt_mesh_model *model, - u16_t key_idx) -{ - struct bt_test_cb *cb; - - SYS_SLIST_FOR_EACH_CONTAINER(&cb_slist, cb, node) { - if (cb->mesh_model_bound) { - cb->mesh_model_bound(addr, model, key_idx); - } - } -} - -void bt_test_mesh_model_unbound(u16_t addr, struct bt_mesh_model *model, - u16_t key_idx) -{ - struct bt_test_cb *cb; - - SYS_SLIST_FOR_EACH_CONTAINER(&cb_slist, cb, node) { - if (cb->mesh_model_unbound) { - cb->mesh_model_unbound(addr, model, key_idx); - } - } -} - -void bt_test_mesh_prov_invalid_bearer(u8_t opcode) -{ - struct bt_test_cb *cb; - - SYS_SLIST_FOR_EACH_CONTAINER(&cb_slist, cb, node) { - if (cb->mesh_prov_invalid_bearer) { - cb->mesh_prov_invalid_bearer(opcode); - } - } -} - -void bt_test_mesh_trans_incomp_timer_exp(void) -{ - struct bt_test_cb *cb; - - SYS_SLIST_FOR_EACH_CONTAINER(&cb_slist, cb, node) { - if (cb->mesh_trans_incomp_timer_exp) { - cb->mesh_trans_incomp_timer_exp(); - } - } -} - -int bt_test_mesh_lpn_group_add(u16_t group) -{ - bt_mesh_lpn_group_add(group); - - return 0; -} - -int bt_test_mesh_lpn_group_remove(u16_t *groups, size_t groups_count) -{ - bt_mesh_lpn_group_del(groups, groups_count); - - return 0; -} - -int bt_test_mesh_rpl_clear(void) -{ - bt_mesh_rpl_clear(); - - return 0; -} - -void bt_test_print_credentials(void) -{ - int i; - u8_t nid; - const u8_t *enc; - const u8_t *priv; - struct bt_mesh_subnet *sub; - struct bt_mesh_app_key *app_key; - - console_printf("IV Index: %08lx\n", (long) bt_mesh.iv_index); - console_printf("Dev key: %s\n", bt_hex(bt_mesh.dev_key, 16)); - - for (i = 0; i < MYNEWT_VAL(BLE_MESH_SUBNET_COUNT); ++i) - { - if (bt_mesh.app_keys[i].net_idx == BT_MESH_KEY_UNUSED) { - continue; - } - - sub = &bt_mesh.sub[i]; - - console_printf("Subnet: %d\n", i); - console_printf("\tNetKeyIdx: %04x\n", - sub->net_idx); - console_printf("\tNetKey: %s\n", - bt_hex(sub->keys[sub->kr_flag].net, 16)); - } - - for (i = 0; i < MYNEWT_VAL(BLE_MESH_APP_KEY_COUNT); ++i) - { - if (bt_mesh.app_keys[i].net_idx == BT_MESH_KEY_UNUSED) { - continue; - } - - sub = &bt_mesh.sub[i]; - app_key = &bt_mesh.app_keys[i]; - - console_printf("AppKey: %d\n", i); - console_printf("\tNetKeyIdx: %04x\n", - app_key->net_idx); - console_printf("\tAppKeyIdx: %04x\n", - app_key->app_idx); - console_printf("\tAppKey: %s\n", - bt_hex(app_key->keys[sub->kr_flag].val, 16)); - } - - for (i = 0; i < MYNEWT_VAL(BLE_MESH_SUBNET_COUNT); ++i) - { - if (bt_mesh.sub[i].net_idx == BT_MESH_KEY_UNUSED) { - continue; - } - - if (friend_cred_get(&bt_mesh.sub[i], BT_MESH_ADDR_UNASSIGNED, - &nid, &enc, &priv)) { - return; - } - - console_printf("Friend cred: %d\n", i); - console_printf("\tNetKeyIdx: %04x\n", - bt_mesh.sub[i].net_idx); - console_printf("\tNID: %02x\n", nid); - console_printf("\tEncKey: %s\n", - bt_hex(enc, 16)); - console_printf("\tPrivKey: %s\n", - bt_hex(priv, 16)); - } -} - -int bt_test_shell_init(void) -{ -#if MYNEWT_VAL(BLE_MESH_SHELL) - return cmd_mesh_init(0, NULL); -#else - return -ENOTSUP; -#endif -} - -int bt_test_bind_app_key_to_model(struct bt_mesh_model *model, u16_t key_idx, u16_t id) -{ - struct bt_mesh_model *found_model; - - found_model = bt_mesh_model_find(bt_mesh_model_elem(model), id); - if (!found_model) { - return STATUS_INVALID_MODEL; - } - - return mod_bind(found_model, key_idx); -} diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/testing.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/testing.h deleted file mode 100644 index 166a9eea6..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/testing.h +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @file testing.h - * @brief Internal API for Bluetooth testing. - */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "mesh/glue.h" -#include "mesh/access.h" - -void bt_test_mesh_model_bound(u16_t addr, struct bt_mesh_model *model, - u16_t key_idx); -void bt_test_mesh_model_unbound(u16_t addr, struct bt_mesh_model *model, - u16_t key_idx); -void bt_test_mesh_prov_invalid_bearer(u8_t opcode); -void bt_test_mesh_net_recv(u8_t ttl, u8_t ctl, u16_t src, u16_t dst, - const void *payload, size_t payload_len); -void bt_test_mesh_trans_incomp_timer_exp(void); -void bt_test_print_credentials(void); diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd_priv.h deleted file mode 100644 index 70f33260a..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd_priv.h +++ /dev/null @@ -1,449 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_ATT_CMD_ -#define H_BLE_ATT_CMD_ - -#include -#include -#include "os/os_mbuf.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct ble_att_hdr { - uint8_t opcode; - uint8_t data[0]; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | Attribute Opcode | 1 | - * | Request Opcode In Error | 1 | - * | Attribute Handle In Error | 2 | - * | Error Code | 1 | - */ -#define BLE_ATT_ERROR_RSP_SZ 5 -struct ble_att_error_rsp { - uint8_t baep_req_op; - uint16_t baep_handle; - uint8_t baep_error_code; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | Attribute Opcode | 1 | - * | Server Rx MTU | 2 | - */ -#define BLE_ATT_MTU_CMD_SZ 3 -struct ble_att_mtu_cmd { - uint16_t bamc_mtu; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | Attribute Opcode | 1 | - * | Starting Handle | 2 | - * | Ending Handle | 2 | - */ -#define BLE_ATT_FIND_INFO_REQ_SZ 5 -struct ble_att_find_info_req { - uint16_t bafq_start_handle; - uint16_t bafq_end_handle; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | Attribute Opcode | 1 | - * | Format | 1 | - * | Information Data | 4 to (ATT_MTU-2) | - */ -#define BLE_ATT_FIND_INFO_RSP_BASE_SZ 2 -struct ble_att_find_info_rsp { - uint8_t bafp_format; - /* Followed by information data. */ -} __attribute__((packed)); - -#define BLE_ATT_FIND_INFO_RSP_FORMAT_16BIT 1 -#define BLE_ATT_FIND_INFO_RSP_FORMAT_128BIT 2 - -#define BLE_ATT_FIND_INFO_IDATA_16_SZ 4 -#define BLE_ATT_FIND_INFO_IDATA_128_SZ 18 - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | Attribute Opcode | 1 | - * | Starting Handle | 2 | - * | Ending Handle | 2 | - * | Attribute Type | 2 | - * | Attribute Value | 0 to (ATT_MTU-7) | - */ -#define BLE_ATT_FIND_TYPE_VALUE_REQ_BASE_SZ 7 -struct ble_att_find_type_value_req { - uint16_t bavq_start_handle; - uint16_t bavq_end_handle; - uint16_t bavq_attr_type; - uint16_t bavq_value[0]; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | Attribute Opcode | 1 | - * | Information Data | 4 to (ATT_MTU-1) | - */ -#define BLE_ATT_FIND_TYPE_VALUE_RSP_BASE_SZ 1 -#define BLE_ATT_FIND_TYPE_VALUE_HINFO_BASE_SZ 4 - -struct ble_att_handle_group { - uint16_t attr_handle; - uint16_t group_end_handle; -} __attribute__((packed)); - -struct ble_att_find_type_value_rsp { - struct ble_att_handle_group list[0]; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | Attribute Opcode | 1 | - * | Starting Handle | 2 | - * | Ending Handle | 2 | - * | Attribute Type | 2 or 16 | - */ -#define BLE_ATT_READ_TYPE_REQ_BASE_SZ 5 -#define BLE_ATT_READ_TYPE_REQ_SZ_16 7 -#define BLE_ATT_READ_TYPE_REQ_SZ_128 21 -struct ble_att_read_type_req { - uint16_t batq_start_handle; - uint16_t batq_end_handle; - uint8_t uuid[0]; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | Attribute Opcode | 1 | - * | Length | 1 | - * | Attribute Data List | 2 to (ATT_MTU-2) | - */ -#define BLE_ATT_READ_TYPE_RSP_BASE_SZ 2 - -struct ble_att_attr_data_list { - uint16_t handle; - uint8_t value[0]; -} __attribute__((packed)); - -struct ble_att_read_type_rsp { - uint8_t batp_length; - struct ble_att_attr_data_list batp_list[0]; -} __attribute__((packed)); - -#define BLE_ATT_READ_TYPE_ADATA_BASE_SZ 2 -#define BLE_ATT_READ_TYPE_ADATA_SZ_16 6 -#define BLE_ATT_READ_TYPE_ADATA_SZ_128 20 - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | Attribute Opcode | 1 | - * | Attribute Handle | 2 | - */ -#define BLE_ATT_READ_REQ_SZ 3 -struct ble_att_read_req { - uint16_t barq_handle; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | Attribute Opcode | 1 | - * | Attribute Value | 0 to (ATT_MTU-1) | - */ -#define BLE_ATT_READ_RSP_BASE_SZ 1 - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | Attribute Opcode | 1 | - * | Attribute Handle | 2 | - * | Value Offset | 2 | - */ -#define BLE_ATT_READ_BLOB_REQ_SZ 5 -struct ble_att_read_blob_req { - uint16_t babq_handle; - uint16_t babq_offset; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | Attribute Opcode | 1 | - * | Attribute Value | 0 to (ATT_MTU-1) | - */ -#define BLE_ATT_READ_BLOB_RSP_BASE_SZ 1 - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | Attribute Opcode | 1 | - * | Set Of Handles | 4 to (ATT_MTU-1) | - */ -#define BLE_ATT_READ_MULT_REQ_BASE_SZ 1 -struct ble_att_read_mult_req { - uint16_t handles[0]; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | Attribute Opcode | 1 | - * | Set Of Values | 4 to (ATT_MTU-1) | - */ -#define BLE_ATT_READ_MULT_RSP_BASE_SZ 1 - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | Attribute Opcode | 1 | - * | Starting Handle | 2 | - * | Ending Handle | 2 | - * | Attribute Group Type | 2 or 16 | - */ -#define BLE_ATT_READ_GROUP_TYPE_REQ_BASE_SZ 5 -#define BLE_ATT_READ_GROUP_TYPE_REQ_SZ_16 7 -#define BLE_ATT_READ_GROUP_TYPE_REQ_SZ_128 21 -struct ble_att_read_group_type_req { - uint16_t bagq_start_handle; - uint16_t bagq_end_handle; - uint8_t uuid[0]; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | Attribute Opcode | 1 | - * | Length | 1 | - * | Attribute Data List | 2 to (ATT_MTU-2) | - */ -#define BLE_ATT_READ_GROUP_TYPE_RSP_BASE_SZ 2 -struct ble_att_read_group_type_rsp { - uint8_t bagp_length; -} __attribute__((packed)); - -#define BLE_ATT_READ_GROUP_TYPE_ADATA_BASE_SZ 4 -#define BLE_ATT_READ_GROUP_TYPE_ADATA_SZ_16 6 -#define BLE_ATT_READ_GROUP_TYPE_ADATA_SZ_128 20 - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | Attribute Opcode | 1 | - * | Attribute Handle | 2 | - * | Attribute Value | 0 to (ATT_MTU-3) | - */ -#define BLE_ATT_WRITE_REQ_BASE_SZ 3 -struct ble_att_write_req { - uint16_t bawq_handle; - uint8_t value[0]; -} __attribute__((packed)); - -#define BLE_ATT_WRITE_RSP_SZ 1 - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | Attribute Opcode | 1 | - * | Attribute Handle | 2 | - * | Value Offset | 2 | - * | Part Attribute Value | 0 to (ATT_MTU-5) | - */ -#define BLE_ATT_PREP_WRITE_CMD_BASE_SZ 5 -struct ble_att_prep_write_cmd { - uint16_t bapc_handle; - uint16_t bapc_offset; - uint16_t bapc_value[0]; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | Attribute Opcode | 1 | - * | Flags | 1 | - */ -#define BLE_ATT_EXEC_WRITE_REQ_SZ 2 -struct ble_att_exec_write_req { - uint8_t baeq_flags; -} __attribute__((packed)); - -#define BLE_ATT_EXEC_WRITE_F_CANCEL 0x00 -#define BLE_ATT_EXEC_WRITE_F_EXECUTE 0x01 - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | Attribute Opcode | 1 | - */ -#define BLE_ATT_EXEC_WRITE_RSP_SZ 1 - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | Attribute Opcode | 1 | - * | Attribute Handle | 2 | - * | Attribute Value | 0 to (ATT_MTU-3) | - */ -#define BLE_ATT_NOTIFY_REQ_BASE_SZ 3 -struct ble_att_notify_req { - uint16_t banq_handle; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | Attribute Opcode | 1 | - * | Attribute Handle | 2 | - * | Attribute Value | 0 to (ATT_MTU-3) | - */ -#define BLE_ATT_INDICATE_REQ_BASE_SZ 3 -struct ble_att_indicate_req { - uint16_t baiq_handle; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | Attribute Opcode | 1 | - */ -#define BLE_ATT_INDICATE_RSP_SZ 1 - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | Attribute Opcode | 1 | - * | Attribute Handle | 2 | - * | Attribute Value | 0 to (ATT_MTU-3) | - */ -#define BLE_ATT_WRITE_CMD_BASE_SZ 3 -struct ble_att_write_cmd { - uint16_t handle; - uint8_t value[0]; -} __attribute__((packed)); - -void ble_att_error_rsp_parse(const void *payload, int len, - struct ble_att_error_rsp *rsp); -void ble_att_error_rsp_write(void *payload, int len, - const struct ble_att_error_rsp *rsp); -void ble_att_mtu_req_parse(const void *payload, int len, - struct ble_att_mtu_cmd *cmd); -void ble_att_mtu_req_write(void *payload, int len, - const struct ble_att_mtu_cmd *cmd); -void ble_att_mtu_rsp_parse(const void *payload, int len, - struct ble_att_mtu_cmd *cmd); -void ble_att_mtu_rsp_write(void *payload, int len, - const struct ble_att_mtu_cmd *cmd); -void ble_att_find_info_req_parse(const void *payload, int len, - struct ble_att_find_info_req *req); -void ble_att_find_info_req_write(void *payload, int len, - const struct ble_att_find_info_req *req); -void ble_att_find_info_rsp_parse(const void *payload, int len, - struct ble_att_find_info_rsp *rsp); -void ble_att_find_info_rsp_write(void *payload, int len, - const struct ble_att_find_info_rsp *rsp); -void ble_att_find_type_value_req_parse( - const void *payload, int len, struct ble_att_find_type_value_req *req); -void ble_att_find_type_value_req_write( - void *payload, int len, const struct ble_att_find_type_value_req *req); -void ble_att_read_type_req_parse(const void *payload, int len, - struct ble_att_read_type_req *req); -void ble_att_read_type_req_write(void *payload, int len, - const struct ble_att_read_type_req *req); -void ble_att_read_type_rsp_parse(const void *payload, int len, - struct ble_att_read_type_rsp *rsp); -void ble_att_read_type_rsp_write(void *payload, int len, - const struct ble_att_read_type_rsp *rsp); -void ble_att_read_req_parse(const void *payload, int len, - struct ble_att_read_req *req); -void ble_att_read_req_write(void *payload, int len, - const struct ble_att_read_req *req); -void ble_att_read_blob_req_parse(const void *payload, int len, - struct ble_att_read_blob_req *req); -void ble_att_read_blob_req_write(void *payload, int len, - const struct ble_att_read_blob_req *req); -void ble_att_read_mult_req_parse(const void *payload, int len); -void ble_att_read_mult_req_write(void *payload, int len); -void ble_att_read_mult_rsp_parse(const void *payload, int len); -void ble_att_read_mult_rsp_write(void *payload, int len); -void ble_att_read_group_type_req_parse( - const void *payload, int len, struct ble_att_read_group_type_req *req); -void ble_att_read_group_type_req_write( - void *payload, int len, const struct ble_att_read_group_type_req *req); -void ble_att_read_group_type_rsp_parse( - const void *payload, int len, struct ble_att_read_group_type_rsp *rsp); -void ble_att_read_group_type_rsp_write( - void *payload, int len, const struct ble_att_read_group_type_rsp *rsp); -void ble_att_write_req_parse(const void *payload, int len, - struct ble_att_write_req *req); -void ble_att_write_req_write(void *payload, int len, - const struct ble_att_write_req *req); -void ble_att_write_cmd_parse(const void *payload, int len, - struct ble_att_write_req *req); -void ble_att_write_cmd_write(void *payload, int len, - const struct ble_att_write_req *req); -void ble_att_prep_write_req_parse(const void *payload, int len, - struct ble_att_prep_write_cmd *cmd); -void ble_att_prep_write_req_write(void *payload, int len, - const struct ble_att_prep_write_cmd *cmd); -void ble_att_prep_write_rsp_parse(const void *payload, int len, - struct ble_att_prep_write_cmd *cmd); -void ble_att_prep_write_rsp_write(void *payload, int len, - const struct ble_att_prep_write_cmd *cmd); -void ble_att_exec_write_req_parse(const void *payload, int len, - struct ble_att_exec_write_req *req); -void ble_att_exec_write_req_write(void *payload, int len, - const struct ble_att_exec_write_req *req); -void ble_att_exec_write_rsp_parse(const void *payload, int len); -void ble_att_exec_write_rsp_write(void *payload, int len); -void ble_att_notify_req_parse(const void *payload, int len, - struct ble_att_notify_req *req); -void ble_att_notify_req_write(void *payload, int len, - const struct ble_att_notify_req *req); -void ble_att_indicate_req_parse(const void *payload, int len, - struct ble_att_indicate_req *req); -void ble_att_indicate_req_write(void *payload, int len, - const struct ble_att_indicate_req *req); -void ble_att_indicate_rsp_parse(const void *payload, int len); -void ble_att_indicate_rsp_write(void *payload, int len); - -void *ble_att_cmd_prepare(uint8_t opcode, size_t len, struct os_mbuf *txom); -void *ble_att_cmd_get(uint8_t opcode, size_t len, struct os_mbuf **txom); -int ble_att_tx(uint16_t conn_handle, struct os_mbuf *txom); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gap_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gap_priv.h deleted file mode 100644 index 2b6b40696..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gap_priv.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_GAP_CONN_ -#define H_BLE_GAP_CONN_ - -#include -#include "syscfg/syscfg.h" -#include "stats/stats.h" -#include "host/ble_gap.h" -#ifdef __cplusplus -extern "C" { -#endif - -struct hci_le_conn_upd_complete; -struct hci_le_conn_param_req; -struct hci_le_conn_complete; -struct hci_disconn_complete; -struct hci_encrypt_change; -struct ble_hs_hci_ack; -struct ble_hs_adv; - -STATS_SECT_START(ble_gap_stats) - STATS_SECT_ENTRY(wl_set) - STATS_SECT_ENTRY(wl_set_fail) - STATS_SECT_ENTRY(adv_stop) - STATS_SECT_ENTRY(adv_stop_fail) - STATS_SECT_ENTRY(adv_start) - STATS_SECT_ENTRY(adv_start_fail) - STATS_SECT_ENTRY(adv_set_data) - STATS_SECT_ENTRY(adv_set_data_fail) - STATS_SECT_ENTRY(adv_rsp_set_data) - STATS_SECT_ENTRY(adv_rsp_set_data_fail) - STATS_SECT_ENTRY(discover) - STATS_SECT_ENTRY(discover_fail) - STATS_SECT_ENTRY(initiate) - STATS_SECT_ENTRY(initiate_fail) - STATS_SECT_ENTRY(terminate) - STATS_SECT_ENTRY(terminate_fail) - STATS_SECT_ENTRY(cancel) - STATS_SECT_ENTRY(cancel_fail) - STATS_SECT_ENTRY(update) - STATS_SECT_ENTRY(update_fail) - STATS_SECT_ENTRY(connect_mst) - STATS_SECT_ENTRY(connect_slv) - STATS_SECT_ENTRY(disconnect) - STATS_SECT_ENTRY(rx_disconnect) - STATS_SECT_ENTRY(rx_update_complete) - STATS_SECT_ENTRY(rx_adv_report) - STATS_SECT_ENTRY(rx_conn_complete) - STATS_SECT_ENTRY(discover_cancel) - STATS_SECT_ENTRY(discover_cancel_fail) - STATS_SECT_ENTRY(security_initiate) - STATS_SECT_ENTRY(security_initiate_fail) -STATS_SECT_END - -extern STATS_SECT_DECL(ble_gap_stats) ble_gap_stats; - -#define BLE_GAP_CONN_MODE_MAX 3 -#define BLE_GAP_DISC_MODE_MAX 3 - -#if MYNEWT_VAL(BLE_EXT_ADV) && NIMBLE_BLE_SCAN -void ble_gap_rx_le_scan_timeout(void); -#endif - -#if MYNEWT_VAL(BLE_EXT_ADV) -void ble_gap_rx_ext_adv_report(struct ble_gap_ext_disc_desc *desc); -void ble_gap_rx_adv_set_terminated(const struct ble_hci_ev_le_subev_adv_set_terminated *ev); -#if MYNEWT_VAL(BLE_PERIODIC_ADV) -void ble_gap_rx_peroidic_adv_sync_estab(const struct ble_hci_ev_le_subev_periodic_adv_sync_estab *ev); -void ble_gap_rx_periodic_adv_rpt(const struct ble_hci_ev_le_subev_periodic_adv_rpt *ev); -void ble_gap_rx_periodic_adv_sync_lost(const struct ble_hci_ev_le_subev_periodic_adv_sync_lost *ev); -void ble_gap_rx_periodic_adv_sync_transfer(const struct ble_hci_ev_le_subev_periodic_adv_sync_transfer *ev); -#endif -void ble_gap_rx_scan_req_rcvd(const struct ble_hci_ev_le_subev_scan_req_rcvd *ev); -#endif -void ble_gap_rx_adv_report(struct ble_gap_disc_desc *desc); -void ble_gap_rx_rd_rem_sup_feat_complete(const struct ble_hci_ev_le_subev_rd_rem_used_feat *ev); - -struct ble_gap_conn_complete -{ - uint8_t status; - uint16_t connection_handle; - uint8_t role; - uint8_t peer_addr_type; - uint8_t peer_addr[BLE_DEV_ADDR_LEN]; - uint16_t conn_itvl; - uint16_t conn_latency; - uint16_t supervision_timeout; - uint8_t master_clk_acc; - uint8_t local_rpa[BLE_DEV_ADDR_LEN]; - uint8_t peer_rpa[BLE_DEV_ADDR_LEN]; -}; - -int ble_gap_rx_conn_complete(struct ble_gap_conn_complete *evt, uint8_t instance); -void ble_gap_rx_disconn_complete(const struct ble_hci_ev_disconn_cmp *ev); -void ble_gap_rx_update_complete(const struct ble_hci_ev_le_subev_conn_upd_complete *ev); -void ble_gap_rx_param_req(const struct ble_hci_ev_le_subev_rem_conn_param_req *ev); -int ble_gap_rx_l2cap_update_req(uint16_t conn_handle, - struct ble_gap_upd_params *params); -void ble_gap_rx_phy_update_complete(const struct ble_hci_ev_le_subev_phy_update_complete *ev); -void ble_gap_enc_event(uint16_t conn_handle, int status, - int security_restored, int bonded); -void ble_gap_passkey_event(uint16_t conn_handle, - struct ble_gap_passkey_params *passkey_params); -void ble_gap_notify_rx_event(uint16_t conn_handle, uint16_t attr_handle, - struct os_mbuf *om, int is_indication); -void ble_gap_notify_tx_event(int status, uint16_t conn_handle, - uint16_t attr_handle, int is_indication); -void ble_gap_subscribe_event(uint16_t conn_handle, uint16_t attr_handle, - uint8_t reason, - uint8_t prev_notify, uint8_t cur_notify, - uint8_t prev_indicate, uint8_t cur_indicate); -void ble_gap_mtu_event(uint16_t conn_handle, uint16_t cid, uint16_t mtu); -void ble_gap_identity_event(uint16_t conn_handle); -int ble_gap_repeat_pairing_event(const struct ble_gap_repeat_pairing *rp); -int ble_gap_master_in_progress(void); - -void ble_gap_preempt(void); -void ble_gap_preempt_done(void); - -int ble_gap_terminate_with_conn(struct ble_hs_conn *conn, uint8_t hci_reason); -void ble_gap_conn_broken(uint16_t conn_handle, int reason); -void ble_gap_reset_state(int reason); -int32_t ble_gap_timer(void); - -int ble_gap_init(void); -void ble_gap_deinit(void); - -#if MYNEWT_VAL(BLE_HS_DEBUG) -int ble_gap_dbg_update_active(uint16_t conn_handle); -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gatt_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gatt_priv.h deleted file mode 100644 index 4a59635b8..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gatt_priv.h +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_GATT_PRIV_ -#define H_BLE_GATT_PRIV_ - -#include "syscfg/syscfg.h" -#include "stats/stats.h" -#include "host/ble_gatt.h" -#ifdef __cplusplus -extern "C" { -#endif - -struct ble_att_read_type_adata; -struct ble_att_find_type_value_hinfo; -struct ble_att_find_info_idata; -struct ble_att_read_group_type_adata; -struct ble_att_prep_write_cmd; - -STATS_SECT_START(ble_gattc_stats) - STATS_SECT_ENTRY(mtu) - STATS_SECT_ENTRY(mtu_fail) - STATS_SECT_ENTRY(disc_all_svcs) - STATS_SECT_ENTRY(disc_all_svcs_fail) - STATS_SECT_ENTRY(disc_svc_uuid) - STATS_SECT_ENTRY(disc_svc_uuid_fail) - STATS_SECT_ENTRY(find_inc_svcs) - STATS_SECT_ENTRY(find_inc_svcs_fail) - STATS_SECT_ENTRY(disc_all_chrs) - STATS_SECT_ENTRY(disc_all_chrs_fail) - STATS_SECT_ENTRY(disc_chrs_uuid) - STATS_SECT_ENTRY(disc_chrs_uuid_fail) - STATS_SECT_ENTRY(disc_all_dscs) - STATS_SECT_ENTRY(disc_all_dscs_fail) - STATS_SECT_ENTRY(read) - STATS_SECT_ENTRY(read_fail) - STATS_SECT_ENTRY(read_uuid) - STATS_SECT_ENTRY(read_uuid_fail) - STATS_SECT_ENTRY(read_long) - STATS_SECT_ENTRY(read_long_fail) - STATS_SECT_ENTRY(read_mult) - STATS_SECT_ENTRY(read_mult_fail) - STATS_SECT_ENTRY(write_no_rsp) - STATS_SECT_ENTRY(write_no_rsp_fail) - STATS_SECT_ENTRY(write) - STATS_SECT_ENTRY(write_fail) - STATS_SECT_ENTRY(write_long) - STATS_SECT_ENTRY(write_long_fail) - STATS_SECT_ENTRY(write_reliable) - STATS_SECT_ENTRY(write_reliable_fail) - STATS_SECT_ENTRY(notify) - STATS_SECT_ENTRY(notify_fail) - STATS_SECT_ENTRY(indicate) - STATS_SECT_ENTRY(indicate_fail) - STATS_SECT_ENTRY(proc_timeout) -STATS_SECT_END -extern STATS_SECT_DECL(ble_gattc_stats) ble_gattc_stats; - -STATS_SECT_START(ble_gatts_stats) - STATS_SECT_ENTRY(svcs) - STATS_SECT_ENTRY(chrs) - STATS_SECT_ENTRY(dscs) - STATS_SECT_ENTRY(svc_def_reads) - STATS_SECT_ENTRY(svc_inc_reads) - STATS_SECT_ENTRY(chr_def_reads) - STATS_SECT_ENTRY(chr_val_reads) - STATS_SECT_ENTRY(chr_val_writes) - STATS_SECT_ENTRY(dsc_reads) - STATS_SECT_ENTRY(dsc_writes) -STATS_SECT_END -extern STATS_SECT_DECL(ble_gatts_stats) ble_gatts_stats; - -#define BLE_GATT_CHR_DECL_SZ_16 5 -#define BLE_GATT_CHR_DECL_SZ_128 19 - -typedef uint8_t ble_gatts_conn_flags; - -struct ble_gatts_conn { - struct ble_gatts_clt_cfg *clt_cfgs; - int num_clt_cfgs; - - uint16_t indicate_val_handle; -}; - -/*** @client. */ - -int ble_gattc_locked_by_cur_task(void); -void ble_gatts_indicate_fail_notconn(uint16_t conn_handle); - -void ble_gattc_rx_err(uint16_t conn_handle, uint16_t handle, uint16_t status); -void ble_gattc_rx_mtu(uint16_t conn_handle, int status, uint16_t chan_mtu); -void ble_gattc_rx_read_type_adata(uint16_t conn_handle, - struct ble_att_read_type_adata *adata); -void ble_gattc_rx_read_type_complete(uint16_t conn_handle, int status); -void ble_gattc_rx_read_rsp(uint16_t conn_handle, int status, - struct os_mbuf **rxom); -void ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, int status, - struct os_mbuf **rxom); -void ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, int status, - struct os_mbuf **rxom); -void ble_gattc_rx_read_group_type_adata( - uint16_t conn_handle, struct ble_att_read_group_type_adata *adata); -void ble_gattc_rx_read_group_type_complete(uint16_t conn_handle, int rc); -void ble_gattc_rx_find_type_value_hinfo( - uint16_t conn_handle, struct ble_att_find_type_value_hinfo *hinfo); -void ble_gattc_rx_find_type_value_complete(uint16_t conn_handle, int status); -void ble_gattc_rx_write_rsp(uint16_t conn_handle); -void ble_gattc_rx_prep_write_rsp(uint16_t conn_handle, int status, - uint16_t handle, uint16_t offset, - struct os_mbuf **rxom); -void ble_gattc_rx_exec_write_rsp(uint16_t conn_handle, int status); -void ble_gattc_rx_indicate_rsp(uint16_t conn_handle); -void ble_gattc_rx_find_info_idata(uint16_t conn_handle, - struct ble_att_find_info_idata *idata); -void ble_gattc_rx_find_info_complete(uint16_t conn_handle, int status); -void ble_gattc_connection_txable(uint16_t conn_handle); -void ble_gattc_connection_broken(uint16_t conn_handle); -int32_t ble_gattc_timer(void); - -int ble_gattc_any_jobs(void); -int ble_gattc_init(void); - -/*** @server. */ -#define BLE_GATTS_CLT_CFG_F_NOTIFY 0x0001 -#define BLE_GATTS_CLT_CFG_F_INDICATE 0x0002 -#define BLE_GATTS_CLT_CFG_F_MODIFIED 0x0080 /* Internal only. */ -#define BLE_GATTS_CLT_CFG_F_RESERVED 0xfffc - -#define BLE_GATTS_INC_SVC_LEN_NO_UUID 4 -#define BLE_GATTS_INC_SVC_LEN_UUID 6 - -/** - * Contains counts of resources required by the GATT server. The contents of - * this struct are generally used to populate a configuration struct before - * the host is initialized. - */ -struct ble_gatt_resources { - /** Number of services. */ - uint16_t svcs; - - /** Number of included services. */ - uint16_t incs; - - /** Number of characteristics. */ - uint16_t chrs; - - /** Number of descriptors. */ - uint16_t dscs; - - /** - * Number of client characteristic configuration descriptors. Each of - * these also contributes to the total descriptor count. - */ - uint16_t cccds; - - /** Total number of ATT attributes. */ - uint16_t attrs; -}; - -int ble_gatts_rx_indicate_ack(uint16_t conn_handle, uint16_t chr_val_handle); -int ble_gatts_send_next_indicate(uint16_t conn_handle); -void ble_gatts_tx_notifications(void); -void ble_gatts_bonding_established(uint16_t conn_handle); -void ble_gatts_bonding_restored(uint16_t conn_handle); -void ble_gatts_connection_broken(uint16_t conn_handle); -void ble_gatts_lcl_svc_foreach(ble_gatt_svc_foreach_fn cb, void *arg); -int ble_gatts_register_svcs(const struct ble_gatt_svc_def *svcs, - ble_gatt_register_fn *register_cb, - void *cb_arg); -int ble_gatts_clt_cfg_access(uint16_t conn_handle, uint16_t attr_handle, - uint8_t op, uint16_t offset, struct os_mbuf **om, - void *arg); - -/*** @misc. */ -int ble_gatts_conn_can_alloc(void); -int ble_gatts_conn_init(struct ble_gatts_conn *gatts_conn); -int ble_gatts_init(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv_priv.h deleted file mode 100644 index 5c8a6ecc9..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv_priv.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_HS_ADV_PRIV_ -#define H_BLE_HS_ADV_PRIV_ - -#ifdef __cplusplus -extern "C" { -#endif - -int ble_hs_adv_set_flat(uint8_t type, int data_len, const void *data, - uint8_t *dst, uint8_t *dst_len, uint8_t max_len); -int ble_hs_adv_find_field(uint8_t type, const uint8_t *data, uint8_t length, - const struct ble_hs_adv_field **out); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn_priv.h deleted file mode 100644 index 0e451194d..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn_priv.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_HS_CONN_ -#define H_BLE_HS_CONN_ - -#include -#include "ble_l2cap_priv.h" -#include "ble_gatt_priv.h" -#include "ble_att_priv.h" -#ifdef __cplusplus -extern "C" { -#endif - -struct hci_le_conn_complete; -struct hci_create_conn; -struct ble_l2cap_chan; - -typedef uint8_t ble_hs_conn_flags_t; - -#define BLE_HS_CONN_F_MASTER 0x01 -#define BLE_HS_CONN_F_TERMINATING 0x02 -#define BLE_HS_CONN_F_TX_FRAG 0x04 /* Cur ACL packet partially txed. */ - -#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) -#define BLE_HS_CONN_L2CAP_COC_CID_MASK_LEN_REM \ - ((MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) % (8 * sizeof(uint32_t))) ? 1 : 0) - -#define BLE_HS_CONN_L2CAP_COC_CID_MASK_LEN \ - (MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) / (8 * sizeof(uint32_t)) + \ - BLE_HS_CONN_L2CAP_COC_CID_MASK_LEN_REM) -#endif - -struct ble_hs_conn { - SLIST_ENTRY(ble_hs_conn) bhc_next; - uint16_t bhc_handle; - uint8_t bhc_our_addr_type; -#if MYNEWT_VAL(BLE_EXT_ADV) - uint8_t bhc_our_rnd_addr[6]; -#endif - ble_addr_t bhc_peer_addr; - ble_addr_t bhc_our_rpa_addr; - ble_addr_t bhc_peer_rpa_addr; - - uint16_t bhc_itvl; - uint16_t bhc_latency; - uint16_t bhc_supervision_timeout; - uint8_t bhc_master_clock_accuracy; - - uint32_t supported_feat; - - ble_hs_conn_flags_t bhc_flags; - - struct ble_l2cap_chan_list bhc_channels; - struct ble_l2cap_chan *bhc_rx_chan; /* Channel rxing current packet. */ - ble_npl_time_t bhc_rx_timeout; -#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) - uint32_t l2cap_coc_cid_mask[BLE_HS_CONN_L2CAP_COC_CID_MASK_LEN]; -#endif - - /** - * Count of packets sent over this connection that the controller has not - * transmitted or flushed yet. - */ - uint16_t bhc_outstanding_pkts; - -#if MYNEWT_VAL(BLE_HS_FLOW_CTRL) - /** - * Count of packets received over this connection that have been processed - * and freed. - */ - uint16_t bhc_completed_pkts; -#endif - - /** Queue of outgoing packets that could not be sent. */ - STAILQ_HEAD(, os_mbuf_pkthdr) bhc_tx_q; - - struct ble_att_svr_conn bhc_att_svr; - struct ble_gatts_conn bhc_gatt_svr; - - struct ble_gap_sec_state bhc_sec_state; - - ble_gap_event_fn *bhc_cb; - void *bhc_cb_arg; - -#if MYNEWT_VAL(BLE_PERIODIC_ADV) - struct ble_hs_periodic_sync *psync; -#endif -}; - -struct ble_hs_conn_addrs { - ble_addr_t our_id_addr; - ble_addr_t peer_id_addr; - ble_addr_t our_ota_addr; - ble_addr_t peer_ota_addr; -}; - -int ble_hs_conn_can_alloc(void); -struct ble_hs_conn *ble_hs_conn_alloc(uint16_t conn_handle); -void ble_hs_conn_free(struct ble_hs_conn *conn); -void ble_hs_conn_insert(struct ble_hs_conn *conn); -void ble_hs_conn_remove(struct ble_hs_conn *conn); -struct ble_hs_conn *ble_hs_conn_find(uint16_t conn_handle); -struct ble_hs_conn *ble_hs_conn_find_assert(uint16_t conn_handle); -struct ble_hs_conn *ble_hs_conn_find_by_addr(const ble_addr_t *addr); -struct ble_hs_conn *ble_hs_conn_find_by_idx(int idx); -int ble_hs_conn_exists(uint16_t conn_handle); -struct ble_hs_conn *ble_hs_conn_first(void); -struct ble_l2cap_chan *ble_hs_conn_chan_find_by_scid(struct ble_hs_conn *conn, - uint16_t cid); -struct ble_l2cap_chan *ble_hs_conn_chan_find_by_dcid(struct ble_hs_conn *conn, - uint16_t cid); -bool ble_hs_conn_chan_exist(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan); -int ble_hs_conn_chan_insert(struct ble_hs_conn *conn, - struct ble_l2cap_chan *chan); -void ble_hs_conn_delete_chan(struct ble_hs_conn *conn, - struct ble_l2cap_chan *chan); - -void ble_hs_conn_addrs(const struct ble_hs_conn *conn, - struct ble_hs_conn_addrs *addrs); -int32_t ble_hs_conn_timer(void); - -typedef int ble_hs_conn_foreach_fn(struct ble_hs_conn *conn, void *arg); -void ble_hs_conn_foreach(ble_hs_conn_foreach_fn *cb, void *arg); - -int ble_hs_conn_init(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_priv.h deleted file mode 100644 index 362f12cbd..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_priv.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_HS_HCI_PRIV_ -#define H_BLE_HS_HCI_PRIV_ - -#include "nimble/hci_common.h" -#ifdef __cplusplus -extern "C" { -#endif - -struct ble_hs_conn; -struct os_mbuf; - -#define BLE_HS_HCI_LE_FEAT_ENCRYPTION (0x00000001) -#define BLE_HS_HCI_LE_FEAT_CONN_PARAM_REQUEST (0x00000002) -#define BLE_HS_HCI_LE_FEAT_EXT_REJECT (0x00000004) -#define BLE_HS_HCI_LE_FEAT_SLAVE_FEAT_EXCHANGE (0x00000008) -#define BLE_HS_HCI_LE_FEAT_PING (0x00000010) -#define BLE_HS_HCI_LE_FEAT_DATA_PACKET_LENGTH_EXT (0x00000020) -#define BLE_HS_HCI_LE_FEAT_LL_PRIVACY (0x00000040) -#define BLE_HS_HCI_LE_FEAT_EXT_SCANNER_FILTER_POLICIES (0x00000080) -#define BLE_HS_HCI_LE_FEAT_2M_PHY (0x00000100) -#define BLE_HS_HCI_LE_FEAT_STABLE_MOD_INDEX_TX (0x00000200) -#define BLE_HS_HCI_LE_FEAT_STABLE_MOD_INDEX_RX (0x00000400) -#define BLE_HS_HCI_LE_FEAT_CODED_PHY (0x00000800) -#define BLE_HS_HCI_LE_FEAT_EXT_ADV (0x00001000) -#define BLE_HS_HCI_LE_FEAT_PERIODIC_ADV (0x00002000) -#define BLE_HS_HCI_LE_FEAT_CSA2 (0x00004000) -#define BLE_HS_HCI_LE_FEAT_POWER_CLASS_1 (0x00008000) -#define BLE_HS_HCI_LE_FEAT_MIN_NUM_USED_CHAN (0x00010000) - -struct ble_hs_hci_ack { - int bha_status; /* A BLE_HS_E<...> error; NOT a naked HCI code. */ - const uint8_t *bha_params; - int bha_params_len; - uint16_t bha_opcode; - uint8_t bha_hci_handle; -}; - -#if MYNEWT_VAL(BLE_EXT_ADV) -struct ble_hs_hci_ext_scan_param { - uint8_t scan_type; - uint16_t scan_itvl; - uint16_t scan_window; -}; - -struct ble_hs_hci_ext_conn_params { - uint16_t scan_itvl; - uint16_t scan_window; - uint16_t conn_itvl; - uint16_t conn_windows; -}; - -#if MYNEWT_VAL(BLE_PERIODIC_ADV) -/* Periodic Advertising Parameters */ -struct hci_periodic_adv_params -{ - uint16_t min_interval; - uint16_t max_interval; - uint16_t properties; -}; -#endif -#endif - -extern uint16_t ble_hs_hci_avail_pkts; - -int ble_hs_hci_cmd_tx(uint16_t opcode, const void *cmd, uint8_t cmd_len, - void *rsp, uint8_t rsp_len); -void ble_hs_hci_init(void); -void ble_hs_hci_deinit(void); - -void ble_hs_hci_set_le_supported_feat(uint32_t feat); -uint32_t ble_hs_hci_get_le_supported_feat(void); -void ble_hs_hci_set_hci_version(uint8_t hci_version); -uint8_t ble_hs_hci_get_hci_version(void); - -#if MYNEWT_VAL(BLE_HS_PHONY_HCI_ACKS) -typedef int ble_hs_hci_phony_ack_fn(uint8_t *ack, int ack_buf_len); -void ble_hs_hci_set_phony_ack_cb(ble_hs_hci_phony_ack_fn *cb); -#endif - -int ble_hs_hci_util_read_adv_tx_pwr(int8_t *out_pwr); -int ble_hs_hci_util_rand(void *dst, int len); -int ble_hs_hci_util_read_rssi(uint16_t conn_handle, int8_t *out_rssi); -int ble_hs_hci_util_set_random_addr(const uint8_t *addr); -int ble_hs_hci_util_data_hdr_strip(struct os_mbuf *om, - struct hci_data_hdr *out_hdr); -int ble_hs_hci_evt_process(const struct ble_hci_ev *ev); - -int ble_hs_hci_cmd_send_buf(uint16_t opcode, const void *buf, uint8_t buf_len); -int ble_hs_hci_set_buf_sz(uint16_t pktlen, uint16_t max_pkts); -void ble_hs_hci_add_avail_pkts(uint16_t delta); - -uint16_t ble_hs_hci_util_handle_pb_bc_join(uint16_t handle, uint8_t pb, - uint8_t bc); - -int ble_hs_hci_acl_tx_now(struct ble_hs_conn *conn, struct os_mbuf **om); -int ble_hs_hci_acl_tx(struct ble_hs_conn *conn, struct os_mbuf **om); - -int ble_hs_hci_frag_num_mbufs(void); -int ble_hs_hci_frag_num_mbufs_free(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_id_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_id_priv.h deleted file mode 100644 index 85260ec48..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_id_priv.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_HS_ID_PRIV_ -#define H_BLE_HS_ID_PRIV_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -void ble_hs_id_set_pub(const uint8_t *pub_addr); -int ble_hs_id_addr(uint8_t id_addr_type, const uint8_t **out_id_addr, - int *out_is_nrpa); -int ble_hs_id_use_addr(uint8_t addr_type); -void ble_hs_id_reset(void); -void ble_hs_id_rnd_reset(void); - -#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY) -bool ble_hs_is_rpa(uint8_t *addr, uint8_t addr_type); -int ble_hs_id_set_pseudo_rnd(const uint8_t *); -int ble_hs_id_set_nrpa_rnd(void); -#endif -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync_priv.h deleted file mode 100644 index c82ea7904..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync_priv.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_HS_PERIODIC_SYNC_ -#define H_BLE_HS_PERIODIC_SYNC_ - -#include -#include "os/queue.h" -#ifdef __cplusplus -extern "C" { -#endif - -struct ble_hs_periodic_sync { - SLIST_ENTRY(ble_hs_periodic_sync) next; - uint16_t sync_handle; - ble_addr_t advertiser_addr; - uint8_t adv_sid; - - ble_gap_event_fn *cb; - void *cb_arg; - - struct ble_npl_event lost_ev; -}; - -struct ble_hs_periodic_sync *ble_hs_periodic_sync_alloc(void); -void ble_hs_periodic_sync_free(struct ble_hs_periodic_sync *psync); -void ble_hs_periodic_sync_insert(struct ble_hs_periodic_sync *psync); -void ble_hs_periodic_sync_remove(struct ble_hs_periodic_sync *psync); -struct ble_hs_periodic_sync *ble_hs_periodic_sync_find_by_handle(uint16_t sync_handle); -struct ble_hs_periodic_sync *ble_hs_periodic_sync_find(const ble_addr_t *addr, - uint8_t sid); -struct ble_hs_periodic_sync *ble_hs_periodic_sync_first(void); -int ble_hs_periodic_sync_init(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_priv.h deleted file mode 100644 index 538d07a97..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_priv.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_HS_PRIV_ -#define H_BLE_HS_PRIV_ - -#include -#include -#include "ble_att_cmd_priv.h" -#include "ble_att_priv.h" -#include "ble_gap_priv.h" -#include "ble_gatt_priv.h" -#include "ble_hs_hci_priv.h" -#include "ble_hs_atomic_priv.h" -#include "ble_hs_conn_priv.h" -#include "ble_hs_atomic_priv.h" -#include "ble_hs_mbuf_priv.h" -#include "ble_hs_startup_priv.h" -#include "ble_l2cap_priv.h" -#include "ble_l2cap_sig_priv.h" -#include "ble_l2cap_coc_priv.h" -#include "ble_sm_priv.h" -#include "ble_hs_adv_priv.h" -#include "ble_hs_flow_priv.h" -#include "ble_hs_pvcy_priv.h" -#include "ble_hs_id_priv.h" -#include "ble_hs_periodic_sync_priv.h" -#include "ble_uuid_priv.h" -#include "host/ble_hs.h" -#include "host/ble_monitor.h" -#include "nimble/nimble_opt.h" -#include "stats/stats.h" -#ifdef __cplusplus -extern "C" { -#endif - -struct ble_hs_conn; -struct ble_l2cap_chan; -struct os_mbuf; -struct os_mempool; -struct os_event; - -#define BLE_HS_SYNC_STATE_BAD 0 -#define BLE_HS_SYNC_STATE_BRINGUP 1 -#define BLE_HS_SYNC_STATE_GOOD 2 - -#define BLE_HS_ENABLED_STATE_OFF 0 -#define BLE_HS_ENABLED_STATE_STOPPING 1 -#define BLE_HS_ENABLED_STATE_ON 2 - -#if NIMBLE_BLE_CONNECT -#define BLE_HS_MAX_CONNECTIONS MYNEWT_VAL(BLE_MAX_CONNECTIONS) -#else -#define BLE_HS_MAX_CONNECTIONS 0 -#endif - -#if !MYNEWT_VAL(BLE_ATT_SVR_QUEUED_WRITE) -#define BLE_HS_ATT_SVR_QUEUED_WRITE_TMO 0 -#else -#define BLE_HS_ATT_SVR_QUEUED_WRITE_TMO \ - MYNEWT_VAL(BLE_ATT_SVR_QUEUED_WRITE_TMO) -#endif - -STATS_SECT_START(ble_hs_stats) - STATS_SECT_ENTRY(conn_create) - STATS_SECT_ENTRY(conn_delete) - STATS_SECT_ENTRY(hci_cmd) - STATS_SECT_ENTRY(hci_event) - STATS_SECT_ENTRY(hci_invalid_ack) - STATS_SECT_ENTRY(hci_unknown_event) - STATS_SECT_ENTRY(hci_timeout) - STATS_SECT_ENTRY(reset) - STATS_SECT_ENTRY(sync) - STATS_SECT_ENTRY(pvcy_add_entry) - STATS_SECT_ENTRY(pvcy_add_entry_fail) -STATS_SECT_END -extern STATS_SECT_DECL(ble_hs_stats) ble_hs_stats; - -extern struct os_mbuf_pool ble_hs_mbuf_pool; -extern uint8_t ble_hs_sync_state; -extern uint8_t ble_hs_enabled_state; - -extern const uint8_t ble_hs_misc_null_addr[6]; - -extern uint16_t ble_hs_max_attrs; -extern uint16_t ble_hs_max_services; -extern uint16_t ble_hs_max_client_configs; - -void ble_hs_process_rx_data_queue(void); -int ble_hs_tx_data(struct os_mbuf *om); -void ble_hs_wakeup_tx(void); -void ble_hs_enqueue_hci_event(uint8_t *hci_evt); -void ble_hs_event_enqueue(struct os_event *ev); - -int ble_hs_hci_rx_evt(uint8_t *hci_ev, void *arg); -int ble_hs_hci_evt_acl_process(struct os_mbuf *om); - -int ble_hs_misc_conn_chan_find(uint16_t conn_handle, uint16_t cid, - struct ble_hs_conn **out_conn, - struct ble_l2cap_chan **out_chan); -int ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid, - struct ble_hs_conn **out_conn, - struct ble_l2cap_chan **out_chan); -uint8_t ble_hs_misc_own_addr_type_to_id(uint8_t addr_type); -uint8_t ble_hs_misc_peer_addr_type_to_id(uint8_t addr_type); -int ble_hs_misc_restore_irks(void); - -int ble_hs_locked_by_cur_task(void); -int ble_hs_is_parent_task(void); -void ble_hs_lock_nested(void); -void ble_hs_unlock_nested(void); -void ble_hs_lock(void); -void ble_hs_unlock(void); -void ble_hs_hw_error(uint8_t hw_code); -void ble_hs_timer_resched(void); -void ble_hs_notifications_sched(void); -struct ble_npl_eventq *ble_hs_evq_get(void); -void ble_hs_stop_init(void); - -struct ble_mqueue { - STAILQ_HEAD(, os_mbuf_pkthdr) head; - struct ble_npl_event ev; -}; - -int ble_mqueue_init(struct ble_mqueue *mq, ble_npl_event_fn *ev_fn, void *ev_arg); -struct os_mbuf *ble_mqueue_get(struct ble_mqueue *mq); -int ble_mqueue_put(struct ble_mqueue *mq, struct ble_npl_eventq *evq, struct os_mbuf *om); - -#if MYNEWT_VAL(BLE_HS_DEBUG) - #define BLE_HS_DBG_ASSERT(x) assert(x) - #define BLE_HS_DBG_ASSERT_EVAL(x) assert(x) -#else - #define BLE_HS_DBG_ASSERT(x) - #define BLE_HS_DBG_ASSERT_EVAL(x) ((void)(x)) -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv_priv.h deleted file mode 100644 index 7bc8a2fe6..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv_priv.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2020 Espressif Systems (Shanghai) PTE LTD - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY) -/* - * An entry in the resolving list. - */ -struct ble_hs_resolv_entry { - uint8_t rl_addr_type; - uint8_t rl_local_irk[16]; - uint8_t rl_peer_irk[16]; - uint8_t rl_identity_addr[BLE_DEV_ADDR_LEN]; - uint8_t rl_pseudo_id[BLE_DEV_ADDR_LEN]; - uint8_t rl_local_rpa[BLE_DEV_ADDR_LEN]; - uint8_t rl_peer_rpa[BLE_DEV_ADDR_LEN]; -}; - -#if MYNEWT_VAL(BLE_STORE_CONFIG_PERSIST) -/* Persist peer records in NVS. XXX Need to handle this in `store` module */ -int ble_store_persist_peer_records(void); -#endif - -struct ble_hs_peer_sec { - ble_addr_t peer_addr; - uint8_t irk[16]; - uint8_t irk_present: 1; -}; -/* - * BLE host peer device record, this helps in storing peer RPA before bond is - * created and IRKs are exchanged. - */ -struct ble_hs_dev_records { - bool rec_used; - uint8_t rand_addr_type; - uint8_t pseudo_addr[BLE_DEV_ADDR_LEN]; - uint8_t rand_addr[BLE_DEV_ADDR_LEN]; - uint8_t identity_addr[BLE_DEV_ADDR_LEN]; - struct ble_hs_peer_sec peer_sec; -}; - -/* Add a device to the resolving list */ -int ble_hs_resolv_list_add(uint8_t *cmdbuf); -int ble_hs_gen_own_private_rnd(void); -uint8_t *ble_hs_get_rpa_local(void); - -/* Remove a device from the resolving list */ -int ble_hs_resolv_list_rmv(uint8_t, uint8_t *); -/* Clear the resolving list and peer dev record */ -void ble_hs_resolv_list_clear_all(void); - -/* Address resolution enable command */ -void ble_hs_resolv_enable(bool); -void ble_hs_resolv_nrpa_enable(void); -void ble_hs_resolv_nrpa_disable(void); - -/* Finds 'addr' in resolving list. Doesnt check if address resolution enabled */ -struct ble_hs_resolv_entry * -ble_hs_resolv_list_find(uint8_t *addr); - -/* Returns true if host based RPA (privacy) is enabled */ -bool ble_host_rpa_enabled(void); - -/* Searches peer device records (RPA) and fetches matching RL, peer_address - * into input parameters if RL is found */ -void -ble_rpa_replace_peer_params_with_rl(uint8_t *, uint8_t *, struct ble_hs_resolv_entry **); - -int ble_rpa_resolv_add_peer_rec(uint8_t *); - -struct ble_hs_dev_records *ble_rpa_get_peer_dev_records(void); -int ble_rpa_get_num_peer_dev_records(void); -void ble_rpa_set_num_peer_dev_records(int); -int ble_rpa_remove_peer_dev_rec(struct ble_hs_dev_records *); -struct ble_hs_dev_records *ble_rpa_find_peer_dev_rec(uint8_t *); - -/* Set the resolvable private address timeout */ -int ble_hs_resolv_set_rpa_tmo(uint16_t); - -/* Resolve a resolvable private address */ -int ble_hs_resolv_rpa(uint8_t *rpa, uint8_t *irk); - -/* Initialize resolv*/ -void ble_hs_resolv_init(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_monitor_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_monitor_priv.h deleted file mode 100644 index 935787040..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_monitor_priv.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_MONITOR_PRIV_ -#define H_BLE_MONITOR_PRIV_ - -#ifdef __cplusplus -extern "C" { -#endif - -#define BLE_MONITOR_OPCODE_NEW_INDEX 0 -#define BLE_MONITOR_OPCODE_DEL_INDEX 1 -#define BLE_MONITOR_OPCODE_COMMAND_PKT 2 -#define BLE_MONITOR_OPCODE_EVENT_PKT 3 -#define BLE_MONITOR_OPCODE_ACL_TX_PKT 4 -#define BLE_MONITOR_OPCODE_ACL_RX_PKT 5 -#define BLE_MONITOR_OPCODE_SCO_TX_PKT 6 -#define BLE_MONITOR_OPCODE_SCO_RX_PKT 7 -#define BLE_MONITOR_OPCODE_OPEN_INDEX 8 -#define BLE_MONITOR_OPCODE_CLOSE_INDEX 9 -#define BLE_MONITOR_OPCODE_INDEX_INFO 10 -#define BLE_MONITOR_OPCODE_VENDOR_DIAG 11 -#define BLE_MONITOR_OPCODE_SYSTEM_NOTE 12 -#define BLE_MONITOR_OPCODE_USER_LOGGING 13 - -#define BLE_MONITOR_EXTHDR_COMMAND_DROPS 1 -#define BLE_MONITOR_EXTHDR_EVENT_DROPS 2 -#define BLE_MONITOR_EXTHDR_ACL_RX_DROPS 3 -#define BLE_MONITOR_EXTHDR_ACL_TX_DROPS 4 -#define BLE_MONITOR_EXTHDR_SCO_RX_DROPS 5 -#define BLE_MONITOR_EXTHDR_SCO_TX_DROPS 6 -#define BLE_MONITOR_EXTHDR_OTHER_DROPS 7 -#define BLE_MONITOR_EXTHDR_TS32 8 - -struct ble_monitor_hdr { - uint16_t data_len; - uint16_t opcode; - uint8_t flags; - uint8_t hdr_len; -} __attribute__((packed)); - -struct ble_monitor_drops_hdr { - uint8_t type_cmd; - uint8_t cmd; - uint8_t type_evt; - uint8_t evt; - uint8_t type_acl_tx; - uint8_t acl_tx; - uint8_t type_acl_rx; - uint8_t acl_rx; - uint8_t type_other; - uint8_t other; -} __attribute__((packed)); - -struct ble_monitor_ts_hdr { - uint8_t type; - uint32_t ts32; -} __attribute__((packed)); - -struct ble_monitor_new_index { - uint8_t type; - uint8_t bus; - uint8_t bdaddr[6]; - char name[8]; -} __attribute__((packed)); - -struct ble_monitor_user_logging { - uint8_t priority; - uint8_t ident_len; -} __attribute__((packed)); - -int ble_monitor_init(void); - -int ble_monitor_send(uint16_t opcode, const void *data, size_t len); - -int ble_monitor_send_om(uint16_t opcode, const struct os_mbuf *om); - -int ble_monitor_new_index(uint8_t bus, uint8_t *addr, const char *name); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/ram/src/ble_store_ram.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/ram/src/ble_store_ram.c deleted file mode 100644 index ab5cdb9f6..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/ram/src/ble_store_ram.c +++ /dev/null @@ -1,497 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/** - * This file implements a simple in-RAM key database for BLE host security - * material and CCCDs. As this database is only ble_store_ramd in RAM, its - * contents are lost when the application terminates. - */ - -#include -#include - -#include "sysinit/sysinit.h" -#include "syscfg/syscfg.h" -#include "host/ble_hs.h" -#include "store/ram/ble_store_ram.h" - -static struct ble_store_value_sec - ble_store_ram_our_secs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)]; -static int ble_store_ram_num_our_secs; - -static struct ble_store_value_sec - ble_store_ram_peer_secs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)]; -static int ble_store_ram_num_peer_secs; - -static struct ble_store_value_cccd - ble_store_ram_cccds[MYNEWT_VAL(BLE_STORE_MAX_CCCDS)]; -static int ble_store_ram_num_cccds; - -/***************************************************************************** - * $sec * - *****************************************************************************/ - -static void -ble_store_ram_print_value_sec(const struct ble_store_value_sec *sec) -{ - if (sec->ltk_present) { - BLE_HS_LOG(DEBUG, "ediv=%u rand=%llu authenticated=%d ltk=", - sec->ediv, sec->rand_num, sec->authenticated); - ble_hs_log_flat_buf(sec->ltk, 16); - BLE_HS_LOG(DEBUG, " "); - } - if (sec->irk_present) { - BLE_HS_LOG(DEBUG, "irk="); - ble_hs_log_flat_buf(sec->irk, 16); - BLE_HS_LOG(DEBUG, " "); - } - if (sec->csrk_present) { - BLE_HS_LOG(DEBUG, "csrk="); - ble_hs_log_flat_buf(sec->csrk, 16); - BLE_HS_LOG(DEBUG, " "); - } - - BLE_HS_LOG(DEBUG, "\n"); -} - -static void -ble_store_ram_print_key_sec(const struct ble_store_key_sec *key_sec) -{ - if (ble_addr_cmp(&key_sec->peer_addr, BLE_ADDR_ANY)) { - BLE_HS_LOG(DEBUG, "peer_addr_type=%d peer_addr=", - key_sec->peer_addr.type); - ble_hs_log_flat_buf(key_sec->peer_addr.val, 6); - BLE_HS_LOG(DEBUG, " "); - } - if (key_sec->ediv_rand_present) { - BLE_HS_LOG(DEBUG, "ediv=0x%02x rand=0x%llx ", - key_sec->ediv, key_sec->rand_num); - } -} - -static int -ble_store_ram_find_sec(const struct ble_store_key_sec *key_sec, - const struct ble_store_value_sec *value_secs, - int num_value_secs) -{ - const struct ble_store_value_sec *cur; - int skipped; - int i; - - skipped = 0; - - for (i = 0; i < num_value_secs; i++) { - cur = value_secs + i; - - if (ble_addr_cmp(&key_sec->peer_addr, BLE_ADDR_ANY)) { - if (ble_addr_cmp(&cur->peer_addr, &key_sec->peer_addr)) { - continue; - } - } - - if (key_sec->ediv_rand_present) { - if (cur->ediv != key_sec->ediv) { - continue; - } - - if (cur->rand_num != key_sec->rand_num) { - continue; - } - } - - if (key_sec->idx > skipped) { - skipped++; - continue; - } - - return i; - } - - return -1; -} - -static int -ble_store_ram_read_our_sec(const struct ble_store_key_sec *key_sec, - struct ble_store_value_sec *value_sec) -{ - int idx; - - idx = ble_store_ram_find_sec(key_sec, ble_store_ram_our_secs, - ble_store_ram_num_our_secs); - if (idx == -1) { - return BLE_HS_ENOENT; - } - - *value_sec = ble_store_ram_our_secs[idx]; - return 0; -} - -static int -ble_store_ram_write_our_sec(const struct ble_store_value_sec *value_sec) -{ - struct ble_store_key_sec key_sec; - int idx; - - BLE_HS_LOG(DEBUG, "persisting our sec; "); - ble_store_ram_print_value_sec(value_sec); - - ble_store_key_from_value_sec(&key_sec, value_sec); - idx = ble_store_ram_find_sec(&key_sec, ble_store_ram_our_secs, - ble_store_ram_num_our_secs); - if (idx == -1) { - if (ble_store_ram_num_our_secs >= MYNEWT_VAL(BLE_STORE_MAX_BONDS)) { - BLE_HS_LOG(DEBUG, "error persisting our sec; too many entries " - "(%d)\n", ble_store_ram_num_our_secs); - return BLE_HS_ESTORE_CAP; - } - - idx = ble_store_ram_num_our_secs; - ble_store_ram_num_our_secs++; - } - - ble_store_ram_our_secs[idx] = *value_sec; - return 0; -} - -static int -ble_store_ram_delete_obj(void *values, int value_size, int idx, - int *num_values) -{ - uint8_t *dst; - uint8_t *src; - int move_count; - - (*num_values)--; - if (idx < *num_values) { - dst = values; - dst += idx * value_size; - src = dst + value_size; - - move_count = *num_values - idx; - memmove(dst, src, move_count); - } - - return 0; -} - -static int -ble_store_ram_delete_sec(const struct ble_store_key_sec *key_sec, - struct ble_store_value_sec *value_secs, - int *num_value_secs) -{ - int idx; - int rc; - - idx = ble_store_ram_find_sec(key_sec, value_secs, *num_value_secs); - if (idx == -1) { - return BLE_HS_ENOENT; - } - - rc = ble_store_ram_delete_obj(value_secs, sizeof *value_secs, idx, - num_value_secs); - if (rc != 0) { - return rc; - } - - return 0; -} - -static int -ble_store_ram_delete_our_sec(const struct ble_store_key_sec *key_sec) -{ - int rc; - - rc = ble_store_ram_delete_sec(key_sec, ble_store_ram_our_secs, - &ble_store_ram_num_our_secs); - if (rc != 0) { - return rc; - } - - return 0; -} - -static int -ble_store_ram_delete_peer_sec(const struct ble_store_key_sec *key_sec) -{ - int rc; - - rc = ble_store_ram_delete_sec(key_sec, ble_store_ram_peer_secs, - &ble_store_ram_num_peer_secs); - if (rc != 0) { - return rc; - } - - return 0; -} - -static int -ble_store_ram_read_peer_sec(const struct ble_store_key_sec *key_sec, - struct ble_store_value_sec *value_sec) -{ - int idx; - - idx = ble_store_ram_find_sec(key_sec, ble_store_ram_peer_secs, - ble_store_ram_num_peer_secs); - if (idx == -1) { - return BLE_HS_ENOENT; - } - - *value_sec = ble_store_ram_peer_secs[idx]; - return 0; -} - -static int -ble_store_ram_write_peer_sec(const struct ble_store_value_sec *value_sec) -{ - struct ble_store_key_sec key_sec; - int idx; - - BLE_HS_LOG(DEBUG, "persisting peer sec; "); - ble_store_ram_print_value_sec(value_sec); - - ble_store_key_from_value_sec(&key_sec, value_sec); - idx = ble_store_ram_find_sec(&key_sec, ble_store_ram_peer_secs, - ble_store_ram_num_peer_secs); - if (idx == -1) { - if (ble_store_ram_num_peer_secs >= MYNEWT_VAL(BLE_STORE_MAX_BONDS)) { - BLE_HS_LOG(DEBUG, "error persisting peer sec; too many entries " - "(%d)\n", ble_store_ram_num_peer_secs); - return BLE_HS_ESTORE_CAP; - } - - idx = ble_store_ram_num_peer_secs; - ble_store_ram_num_peer_secs++; - } - - ble_store_ram_peer_secs[idx] = *value_sec; - return 0; -} - -/***************************************************************************** - * $cccd * - *****************************************************************************/ - -static int -ble_store_ram_find_cccd(const struct ble_store_key_cccd *key) -{ - struct ble_store_value_cccd *cccd; - int skipped; - int i; - - skipped = 0; - for (i = 0; i < ble_store_ram_num_cccds; i++) { - cccd = ble_store_ram_cccds + i; - - if (ble_addr_cmp(&key->peer_addr, BLE_ADDR_ANY)) { - if (ble_addr_cmp(&cccd->peer_addr, &key->peer_addr)) { - continue; - } - } - - if (key->chr_val_handle != 0) { - if (cccd->chr_val_handle != key->chr_val_handle) { - continue; - } - } - - if (key->idx > skipped) { - skipped++; - continue; - } - - return i; - } - - return -1; -} - -static int -ble_store_ram_delete_cccd(const struct ble_store_key_cccd *key_cccd) -{ - int idx; - int rc; - - idx = ble_store_ram_find_cccd(key_cccd); - if (idx == -1) { - return BLE_HS_ENOENT; - } - - rc = ble_store_ram_delete_obj(ble_store_ram_cccds, - sizeof *ble_store_ram_cccds, - idx, - &ble_store_ram_num_cccds); - if (rc != 0) { - return rc; - } - - return 0; -} - -static int -ble_store_ram_read_cccd(const struct ble_store_key_cccd *key_cccd, - struct ble_store_value_cccd *value_cccd) -{ - int idx; - - idx = ble_store_ram_find_cccd(key_cccd); - if (idx == -1) { - return BLE_HS_ENOENT; - } - - *value_cccd = ble_store_ram_cccds[idx]; - return 0; -} - -static int -ble_store_ram_write_cccd(const struct ble_store_value_cccd *value_cccd) -{ - struct ble_store_key_cccd key_cccd; - int idx; - - ble_store_key_from_value_cccd(&key_cccd, value_cccd); - idx = ble_store_ram_find_cccd(&key_cccd); - if (idx == -1) { - if (ble_store_ram_num_cccds >= MYNEWT_VAL(BLE_STORE_MAX_CCCDS)) { - BLE_HS_LOG(DEBUG, "error persisting cccd; too many entries (%d)\n", - ble_store_ram_num_cccds); - return BLE_HS_ESTORE_CAP; - } - - idx = ble_store_ram_num_cccds; - ble_store_ram_num_cccds++; - } - - ble_store_ram_cccds[idx] = *value_cccd; - return 0; -} - -/***************************************************************************** - * $api * - *****************************************************************************/ - -/** - * Searches the database for an object matching the specified criteria. - * - * @return 0 if a key was found; else BLE_HS_ENOENT. - */ -int -ble_store_ram_read(int obj_type, const union ble_store_key *key, - union ble_store_value *value) -{ - int rc; - - switch (obj_type) { - case BLE_STORE_OBJ_TYPE_PEER_SEC: - /* An encryption procedure (bonding) is being attempted. The nimble - * stack is asking us to look in our key database for a long-term key - * corresponding to the specified ediv and random number. - * - * Perform a key lookup and populate the context object with the - * result. The nimble stack will use this key if this function returns - * success. - */ - BLE_HS_LOG(DEBUG, "looking up peer sec; "); - ble_store_ram_print_key_sec(&key->sec); - BLE_HS_LOG(DEBUG, "\n"); - rc = ble_store_ram_read_peer_sec(&key->sec, &value->sec); - return rc; - - case BLE_STORE_OBJ_TYPE_OUR_SEC: - BLE_HS_LOG(DEBUG, "looking up our sec; "); - ble_store_ram_print_key_sec(&key->sec); - BLE_HS_LOG(DEBUG, "\n"); - rc = ble_store_ram_read_our_sec(&key->sec, &value->sec); - return rc; - - case BLE_STORE_OBJ_TYPE_CCCD: - rc = ble_store_ram_read_cccd(&key->cccd, &value->cccd); - return rc; - - default: - return BLE_HS_ENOTSUP; - } -} - -/** - * Adds the specified object to the database. - * - * @return 0 on success; BLE_HS_ESTORE_CAP if the database - * is full. - */ -int -ble_store_ram_write(int obj_type, const union ble_store_value *val) -{ - int rc; - - switch (obj_type) { - case BLE_STORE_OBJ_TYPE_PEER_SEC: - rc = ble_store_ram_write_peer_sec(&val->sec); - return rc; - - case BLE_STORE_OBJ_TYPE_OUR_SEC: - rc = ble_store_ram_write_our_sec(&val->sec); - return rc; - - case BLE_STORE_OBJ_TYPE_CCCD: - rc = ble_store_ram_write_cccd(&val->cccd); - return rc; - - default: - return BLE_HS_ENOTSUP; - } -} - -int -ble_store_ram_delete(int obj_type, const union ble_store_key *key) -{ - int rc; - - switch (obj_type) { - case BLE_STORE_OBJ_TYPE_PEER_SEC: - rc = ble_store_ram_delete_peer_sec(&key->sec); - return rc; - - case BLE_STORE_OBJ_TYPE_OUR_SEC: - rc = ble_store_ram_delete_our_sec(&key->sec); - return rc; - - case BLE_STORE_OBJ_TYPE_CCCD: - rc = ble_store_ram_delete_cccd(&key->cccd); - return rc; - - default: - return BLE_HS_ENOTSUP; - } -} - -void -ble_store_ram_init(void) -{ - /* Ensure this function only gets called by sysinit. */ - SYSINIT_ASSERT_ACTIVE(); - - ble_hs_cfg.store_read_cb = ble_store_ram_read; - ble_hs_cfg.store_write_cb = ble_store_ram_write; - ble_hs_cfg.store_delete_cb = ble_store_ram_delete; - - /* Re-initialize BSS values in case of unit tests. */ - ble_store_ram_num_our_secs = 0; - ble_store_ram_num_peer_secs = 0; - ble_store_ram_num_cccds = 0; -} diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_hw.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_hw.h new file mode 100644 index 000000000..dfac69b60 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_hw.h @@ -0,0 +1,116 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_HW_ +#define H_BLE_HW_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nimble/porting/nimble/include/syscfg/syscfg.h" + +#if defined(ARCH_sim) +#define BLE_USES_HW_WHITELIST (0) +#else +#define BLE_USES_HW_WHITELIST MYNEWT_VAL(BLE_HW_WHITELIST_ENABLE) +#endif + +/* Returns the number of hw whitelist elements */ +uint8_t ble_hw_whitelist_size(void); + +/* Clear the whitelist */ +void ble_hw_whitelist_clear(void); + +/* Remove a device from the hw whitelist */ +void ble_hw_whitelist_rmv(const uint8_t *addr, uint8_t addr_type); + +/* Add a device to the hw whitelist */ +int ble_hw_whitelist_add(const uint8_t *addr, uint8_t addr_type); + +/* Enable hw whitelisting */ +void ble_hw_whitelist_enable(void); + +/* Enable hw whitelisting */ +void ble_hw_whitelist_disable(void); + +/* Boolean function returning true if address matches a whitelist entry */ +int ble_hw_whitelist_match(void); + +/* Encrypt data */ +struct ble_encryption_block; +int ble_hw_encrypt_block(struct ble_encryption_block *ecb); + +/* Random number generation */ +typedef void (*ble_rng_isr_cb_t)(uint8_t rnum); +int ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias); + +/** + * Start the random number generator + * + * @return int + */ +int ble_hw_rng_start(void); + +/** + * Stop the random generator + * + * @return int + */ +int ble_hw_rng_stop(void); + +/** + * Read the random number generator. + * + * @return uint8_t + */ +uint8_t ble_hw_rng_read(void); + +/* Clear the resolving list*/ +void ble_hw_resolv_list_clear(void); + +/* Add a device to the hw resolving list */ +int ble_hw_resolv_list_add(uint8_t *irk); + +/* Remove a device from the hw resolving list */ +void ble_hw_resolv_list_rmv(int index); + +/* Returns the size of the whitelist in HW */ +uint8_t ble_hw_resolv_list_size(void); + +/* Enable the resolving list */ +void ble_hw_resolv_list_enable(void); + +/* Disables resolving list devices */ +void ble_hw_resolv_list_disable(void); + +/* Returns index of resolved address; -1 if not resolved */ +int ble_hw_resolv_list_match(void); + +/* Returns public device address or -1 if not present */ +int ble_hw_get_public_addr(ble_addr_t *addr); + +/* Returns random static address or -1 if not present */ +int ble_hw_get_static_addr(ble_addr_t *addr); + +#ifdef __cplusplus +} +#endif + +#endif /* H_BLE_HW_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll.h new file mode 100644 index 000000000..3b165a706 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll.h @@ -0,0 +1,584 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_LL_ +#define H_BLE_LL_ + +#include "nimble/porting/nimble/include/stats/stats.h" +#include "nimble/porting/nimble/include/os/os_cputime.h" +#include "nimble/nimble/include/nimble/nimble_opt.h" +#include "nimble/nimble/include/nimble/nimble_npl.h" +#include "ble_phy.h" + +#ifdef MYNEWT +#include "./ble_ll_ctrl.h" +#include "hal/hal_system.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if MYNEWT_VAL(OS_CPUTIME_FREQ) != 32768 +#error 32.768kHz clock required +#endif + +#if defined(MYNEWT) && MYNEWT_VAL(BLE_LL_VND_EVENT_ON_ASSERT) +#ifdef NDEBUG +#define BLE_LL_ASSERT(cond) (void(0)) +#else +#define BLE_LL_ASSERT(cond) \ + if (!(cond)) { \ + if (hal_debugger_connected()) { \ + assert(0);\ + } else {\ + ble_ll_hci_ev_send_vendor_err(__FILE__, __LINE__); \ + while(1) {}\ + }\ + } +#endif +#else +#define BLE_LL_ASSERT(cond) assert(cond) +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) +#define BLE_LL_BT5_PHY_SUPPORTED (1) +#else +#define BLE_LL_BT5_PHY_SUPPORTED (0) +#endif + +/* Controller revision. */ +#define BLE_LL_SUB_VERS_NR (0x0000) + +/* Timing jitter as per spec is +/16 usecs */ +#define BLE_LL_JITTER_USECS (16) + +/* Packet queue header definition */ +STAILQ_HEAD(ble_ll_pkt_q, os_mbuf_pkthdr); + +/* + * Global Link Layer data object. There is only one Link Layer data object + * per controller although there may be many instances of the link layer state + * machine running. + */ +struct ble_ll_obj +{ + /* Supported features */ + uint64_t ll_supp_features; + + /* Current Link Layer state */ + uint8_t ll_state; + + /* Number of ACL data packets supported */ + uint8_t ll_num_acl_pkts; + + /* ACL data packet size */ + uint16_t ll_acl_pkt_size; + + /* Preferred PHY's */ + uint8_t ll_pref_tx_phys; + uint8_t ll_pref_rx_phys; + + /* Task event queue */ + struct ble_npl_eventq ll_evq; + + /* Wait for response timer */ + struct hal_timer ll_wfr_timer; + + /* Packet receive queue (and event). Holds received packets from PHY */ + struct ble_npl_event ll_rx_pkt_ev; + struct ble_ll_pkt_q ll_rx_pkt_q; + + /* Packet transmit queue */ + struct ble_npl_event ll_tx_pkt_ev; + struct ble_ll_pkt_q ll_tx_pkt_q; + + /* Data buffer overflow event */ + struct ble_npl_event ll_dbuf_overflow_ev; + + /* Number of completed packets event */ + struct ble_npl_event ll_comp_pkt_ev; + + /* HW error callout */ + struct ble_npl_callout ll_hw_err_timer; +}; +extern struct ble_ll_obj g_ble_ll_data; + +/* Link layer statistics */ +STATS_SECT_START(ble_ll_stats) + STATS_SECT_ENTRY(hci_cmds) + STATS_SECT_ENTRY(hci_cmd_errs) + STATS_SECT_ENTRY(hci_events_sent) + STATS_SECT_ENTRY(bad_ll_state) + STATS_SECT_ENTRY(bad_acl_hdr) + STATS_SECT_ENTRY(no_bufs) + STATS_SECT_ENTRY(rx_adv_pdu_crc_ok) + STATS_SECT_ENTRY(rx_adv_pdu_crc_err) + STATS_SECT_ENTRY(rx_adv_bytes_crc_ok) + STATS_SECT_ENTRY(rx_adv_bytes_crc_err) + STATS_SECT_ENTRY(rx_data_pdu_crc_ok) + STATS_SECT_ENTRY(rx_data_pdu_crc_err) + STATS_SECT_ENTRY(rx_data_bytes_crc_ok) + STATS_SECT_ENTRY(rx_data_bytes_crc_err) + STATS_SECT_ENTRY(rx_adv_malformed_pkts) + STATS_SECT_ENTRY(rx_adv_ind) + STATS_SECT_ENTRY(rx_adv_direct_ind) + STATS_SECT_ENTRY(rx_adv_nonconn_ind) + STATS_SECT_ENTRY(rx_adv_ext_ind) + STATS_SECT_ENTRY(rx_scan_reqs) + STATS_SECT_ENTRY(rx_scan_rsps) + STATS_SECT_ENTRY(rx_connect_reqs) + STATS_SECT_ENTRY(rx_scan_ind) + STATS_SECT_ENTRY(rx_aux_connect_rsp) + STATS_SECT_ENTRY(adv_txg) + STATS_SECT_ENTRY(adv_late_starts) + STATS_SECT_ENTRY(adv_resched_pdu_fail) + STATS_SECT_ENTRY(adv_drop_event) + STATS_SECT_ENTRY(sched_state_conn_errs) + STATS_SECT_ENTRY(sched_state_adv_errs) + STATS_SECT_ENTRY(scan_starts) + STATS_SECT_ENTRY(scan_stops) + STATS_SECT_ENTRY(scan_req_txf) + STATS_SECT_ENTRY(scan_req_txg) + STATS_SECT_ENTRY(scan_rsp_txg) + STATS_SECT_ENTRY(aux_missed_adv) + STATS_SECT_ENTRY(aux_scheduled) + STATS_SECT_ENTRY(aux_received) + STATS_SECT_ENTRY(aux_fired_for_read) + STATS_SECT_ENTRY(aux_allocated) + STATS_SECT_ENTRY(aux_freed) + STATS_SECT_ENTRY(aux_sched_cb) + STATS_SECT_ENTRY(aux_conn_req_tx) + STATS_SECT_ENTRY(aux_conn_rsp_tx) + STATS_SECT_ENTRY(aux_conn_rsp_err) + STATS_SECT_ENTRY(aux_scan_req_tx) + STATS_SECT_ENTRY(aux_scan_rsp_err) + STATS_SECT_ENTRY(aux_chain_cnt) + STATS_SECT_ENTRY(aux_chain_err) + STATS_SECT_ENTRY(aux_scan_drop) + STATS_SECT_ENTRY(adv_evt_dropped) + STATS_SECT_ENTRY(scan_timer_stopped) + STATS_SECT_ENTRY(scan_timer_restarted) + STATS_SECT_ENTRY(periodic_adv_drop_event) + STATS_SECT_ENTRY(periodic_chain_drop_event) + STATS_SECT_ENTRY(sync_event_failed) + STATS_SECT_ENTRY(sync_received) + STATS_SECT_ENTRY(sync_chain_failed) + STATS_SECT_ENTRY(sync_missed_err) + STATS_SECT_ENTRY(sync_crc_err) + STATS_SECT_ENTRY(sync_rx_buf_err) + STATS_SECT_ENTRY(sync_scheduled) + STATS_SECT_ENTRY(sched_state_sync_errs) + STATS_SECT_ENTRY(sched_invalid_pdu) +STATS_SECT_END +extern STATS_SECT_DECL(ble_ll_stats) ble_ll_stats; + +/* States */ +#define BLE_LL_STATE_STANDBY (0) +#define BLE_LL_STATE_ADV (1) +#define BLE_LL_STATE_SCANNING (2) +#define BLE_LL_STATE_INITIATING (3) +#define BLE_LL_STATE_CONNECTION (4) +#define BLE_LL_STATE_DTM (5) +#define BLE_LL_STATE_SYNC (6) + +/* LL Features */ +#define BLE_LL_FEAT_LE_ENCRYPTION (0x0000000001) +#define BLE_LL_FEAT_CONN_PARM_REQ (0x0000000002) +#define BLE_LL_FEAT_EXTENDED_REJ (0x0000000004) +#define BLE_LL_FEAT_SLAVE_INIT (0x0000000008) +#define BLE_LL_FEAT_LE_PING (0x0000000010) +#define BLE_LL_FEAT_DATA_LEN_EXT (0x0000000020) +#define BLE_LL_FEAT_LL_PRIVACY (0x0000000040) +#define BLE_LL_FEAT_EXT_SCAN_FILT (0x0000000080) +#define BLE_LL_FEAT_LE_2M_PHY (0x0000000100) +#define BLE_LL_FEAT_STABLE_MOD_ID_TX (0x0000000200) +#define BLE_LL_FEAT_STABLE_MOD_ID_RX (0x0000000400) +#define BLE_LL_FEAT_LE_CODED_PHY (0x0000000800) +#define BLE_LL_FEAT_EXT_ADV (0x0000001000) +#define BLE_LL_FEAT_PERIODIC_ADV (0x0000002000) +#define BLE_LL_FEAT_CSA2 (0x0000004000) +#define BLE_LL_FEAT_LE_POWER_CLASS_1 (0x0000008000) +#define BLE_LL_FEAT_MIN_USED_CHAN (0x0000010000) +#define BLE_LL_FEAT_CTE_REQ (0x0000020000) +#define BLE_LL_FEAT_CTE_RSP (0x0000040000) +#define BLE_LL_FEAT_CTE_TX (0x0000080000) +#define BLE_LL_FEAT_CTE_RX (0x0000100000) +#define BLE_LL_FEAT_CTE_AOD (0x0000200000) +#define BLE_LL_FEAT_CTE_AOA (0x0000400000) +#define BLE_LL_FEAT_CTE_RECV (0x0000800000) +#define BLE_LL_FEAT_SYNC_TRANS_SEND (0x0001000000) +#define BLE_LL_FEAT_SYNC_TRANS_RECV (0x0002000000) +#define BLE_LL_FEAT_SCA_UPDATE (0x0004000000) +#define BLE_LL_FEAT_REM_PKEY (0x0008000000) +#define BLE_LL_FEAT_CIS_MASTER (0x0010000000) +#define BLE_LL_FEAT_CIS_SLAVE (0x0020000000) +#define BLE_LL_FEAT_ISO_BROADCASTER (0x0040000000) +#define BLE_LL_FEAT_SYNC_RECV (0x0080000000) +#define BLE_LL_FEAT_ISO_HOST_SUPPORT (0x0100000000) +#define BLE_LL_FEAT_POWER_CTRL_REQ (0x0200000000) +#define BLE_LL_FEAT_POWER_CHANGE_IND (0x0400000000) +#define BLE_LL_FEAT_PATH_LOSS_MON (0x0800000000) + +/* This is initial mask, so if feature exchange will not happen, + * but host will want to use this procedure, we will try. If not + * succeed, feature bit will be cleared. + * Look at LL Features above to find out what is allowed + */ +#define BLE_LL_CONN_INITIAL_FEATURES (0x00000022) +#define BLE_LL_CONN_CLEAR_FEATURE(connsm, feature) (connsm->conn_features &= ~(feature)) + +/* All the features which can be controlled by the Host */ +#define BLE_LL_HOST_CONTROLLED_FEATURES (BLE_LL_FEAT_ISO_HOST_SUPPORT) + +/* LL timing */ +#define BLE_LL_IFS (150) /* usecs */ +#define BLE_LL_MAFS (300) /* usecs */ + +/* + * BLE LL device address. Note that element 0 of the array is the LSB and + * is sent over the air first. Byte 5 is the MSB and is the last one sent over + * the air. + */ +#define BLE_DEV_ADDR_LEN (6) /* bytes */ + +struct ble_dev_addr +{ + uint8_t u8[BLE_DEV_ADDR_LEN]; +}; + +#define BLE_IS_DEV_ADDR_STATIC(addr) ((addr->u8[5] & 0xc0) == 0xc0) +#define BLE_IS_DEV_ADDR_RESOLVABLE(addr) ((addr->u8[5] & 0xc0) == 0x40) +#define BLE_IS_DEV_ADDR_UNRESOLVABLE(addr) ((addr->u8[5] & 0xc0) == 0x00) + +/* + * LL packet format + * + * -> Preamble (1/2 bytes) + * -> Access Address (4 bytes) + * -> PDU (2 to 257 octets) + * -> CRC (3 bytes) + */ +#define BLE_LL_PREAMBLE_LEN (1) +#define BLE_LL_ACC_ADDR_LEN (4) +#define BLE_LL_CRC_LEN (3) +#define BLE_LL_PDU_HDR_LEN (2) +#define BLE_LL_MAX_PAYLOAD_LEN (255) +#define BLE_LL_MIN_PDU_LEN (BLE_LL_PDU_HDR_LEN) +#define BLE_LL_MAX_PDU_LEN ((BLE_LL_PDU_HDR_LEN) + (BLE_LL_MAX_PAYLOAD_LEN)) +#define BLE_LL_CRCINIT_ADV (0x555555) + +/* Access address for advertising channels */ +#define BLE_ACCESS_ADDR_ADV (0x8E89BED6) + +/* + * Advertising PDU format: + * -> 2 byte header + * -> LSB contains pdu type, txadd and rxadd bits. + * -> MSB contains length (6 bits). Length is length of payload. Does + * not include the header length itself. + * -> Payload (max 37 bytes) + */ +#define BLE_ADV_PDU_HDR_TYPE_MASK (0x0F) +#define BLE_ADV_PDU_HDR_CHSEL_MASK (0x20) +#define BLE_ADV_PDU_HDR_TXADD_MASK (0x40) +#define BLE_ADV_PDU_HDR_RXADD_MASK (0x80) + +/* Advertising channel PDU types */ +#define BLE_ADV_PDU_TYPE_ADV_IND (0) +#define BLE_ADV_PDU_TYPE_ADV_DIRECT_IND (1) +#define BLE_ADV_PDU_TYPE_ADV_NONCONN_IND (2) +#define BLE_ADV_PDU_TYPE_SCAN_REQ (3) +#define BLE_ADV_PDU_TYPE_SCAN_RSP (4) +#define BLE_ADV_PDU_TYPE_CONNECT_IND (5) +#define BLE_ADV_PDU_TYPE_ADV_SCAN_IND (6) +#define BLE_ADV_PDU_TYPE_ADV_EXT_IND (7) +#define BLE_ADV_PDU_TYPE_AUX_ADV_IND BLE_ADV_PDU_TYPE_ADV_EXT_IND +#define BLE_ADV_PDU_TYPE_AUX_SCAN_RSP BLE_ADV_PDU_TYPE_ADV_EXT_IND +#define BLE_ADV_PDU_TYPE_AUX_SYNC_IND BLE_ADV_PDU_TYPE_ADV_EXT_IND +#define BLE_ADV_PDU_TYPE_AUX_CHAIN_IND BLE_ADV_PDU_TYPE_ADV_EXT_IND +#define BLE_ADV_PDU_TYPE_AUX_CONNECT_REQ BLE_ADV_PDU_TYPE_CONNECT_IND +#define BLE_ADV_PDU_TYPE_AUX_SCAN_REQ BLE_ADV_PDU_TYPE_SCAN_REQ +#define BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP (8) + +/* Extended Header Length (6b) + AdvMode (2b) */ +#define BLE_LL_EXT_ADV_HDR_LEN (1) + +#define BLE_LL_EXT_ADV_ADVA_BIT (0) +#define BLE_LL_EXT_ADV_TARGETA_BIT (1) +#define BLE_LL_EXT_ADV_CTE_INFO_BIT (2) +#define BLE_LL_EXT_ADV_DATA_INFO_BIT (3) +#define BLE_LL_EXT_ADV_AUX_PTR_BIT (4) +#define BLE_LL_EXT_ADV_SYNC_INFO_BIT (5) +#define BLE_LL_EXT_ADV_TX_POWER_BIT (6) + +#define BLE_LL_EXT_ADV_FLAGS_SIZE (1) +#define BLE_LL_EXT_ADV_ADVA_SIZE (6) +#define BLE_LL_EXT_ADV_TARGETA_SIZE (6) +#define BLE_LL_EXT_ADV_DATA_INFO_SIZE (2) +#define BLE_LL_EXT_ADV_AUX_PTR_SIZE (3) +#define BLE_LL_EXT_ADV_SYNC_INFO_SIZE (18) +#define BLE_LL_EXT_ADV_TX_POWER_SIZE (1) + +#define BLE_LL_EXT_ADV_MODE_NON_CONN (0x00) +#define BLE_LL_EXT_ADV_MODE_CONN (0x01) +#define BLE_LL_EXT_ADV_MODE_SCAN (0x02) + +/* If Channel Selection Algorithm #2 is supported */ +#define BLE_ADV_PDU_HDR_CHSEL (0x20) + +/* + * TxAdd and RxAdd bit definitions. A 0 is a public address; a 1 is a + * random address. + */ +#define BLE_ADV_PDU_HDR_TXADD_RAND (0x40) +#define BLE_ADV_PDU_HDR_RXADD_RAND (0x80) + +/* + * Data Channel format + * + * -> Header (2 bytes) + * -> LSB contains llid, nesn, sn and md + * -> MSB contains length (8 bits) + * -> Payload (0 to 251) + * -> MIC (0 or 4 bytes) + */ +#define BLE_LL_DATA_HDR_LLID_MASK (0x03) +#define BLE_LL_DATA_HDR_NESN_MASK (0x04) +#define BLE_LL_DATA_HDR_SN_MASK (0x08) +#define BLE_LL_DATA_HDR_MD_MASK (0x10) +#define BLE_LL_DATA_HDR_RSRVD_MASK (0xE0) +#define BLE_LL_DATA_PDU_MAX_PYLD (251) +#define BLE_LL_DATA_MIC_LEN (4) + +/* LLID definitions */ +#define BLE_LL_LLID_RSRVD (0) +#define BLE_LL_LLID_DATA_FRAG (1) +#define BLE_LL_LLID_DATA_START (2) +#define BLE_LL_LLID_CTRL (3) + +/* + * CONNECT_REQ + * -> InitA (6 bytes) + * -> AdvA (6 bytes) + * -> LLData (22 bytes) + * -> Access address (4 bytes) + * -> CRC init (3 bytes) + * -> WinSize (1 byte) + * -> WinOffset (2 bytes) + * -> Interval (2 bytes) + * -> Latency (2 bytes) + * -> Timeout (2 bytes) + * -> Channel Map (5 bytes) + * -> Hop Increment (5 bits) + * -> SCA (3 bits) + * + * InitA is the initiators public (TxAdd=0) or random (TxAdd=1) address. + * AdvaA is the advertisers public (RxAdd=0) or random (RxAdd=1) address. + * LLData contains connection request data. + * aa: Link Layer's access address + * crc_init: The CRC initialization value used for CRC calculation. + * winsize: The transmit window size = winsize * 1.25 msecs + * winoffset: The transmit window offset = winoffset * 1.25 msecs + * interval: The connection interval = interval * 1.25 msecs. + * latency: connection slave latency = latency + * timeout: Connection supervision timeout = timeout * 10 msecs. + * chanmap: contains channel mapping indicating used and unused data + * channels. Only bits that are 1 are usable. LSB is channel 0. + * hop_inc: Hop increment used for frequency hopping. Random value in + * range of 5 to 16. + */ +#define BLE_CONNECT_REQ_LEN (34) +#define BLE_CONNECT_REQ_PDU_LEN (BLE_CONNECT_REQ_LEN + BLE_LL_PDU_HDR_LEN) + +#define BLE_SCAN_REQ_LEN (12) +#define BLE_SCAN_RSP_MAX_LEN (37) +#define BLE_SCAN_RSP_MAX_EXT_LEN (251) + +#define BLE_LL_ADDR_SUBTYPE_IDENTITY (0) +#define BLE_LL_ADDR_SUBTYPE_RPA (1) +#define BLE_LL_ADDR_SUBTYPE_NRPA (2) + +/*--- External API ---*/ +/* Initialize the Link Layer */ +void ble_ll_init(void); + +/* Reset the Link Layer */ +int ble_ll_reset(void); + +int ble_ll_is_valid_public_addr(const uint8_t *addr); + +/* 'Boolean' function returning true if address is a valid random address */ +int ble_ll_is_valid_random_addr(const uint8_t *addr); + +/* + * Check if given own_addr_type is valid for current controller configuration + * given the random address provided (when applicable) + */ +int ble_ll_is_valid_own_addr_type(uint8_t own_addr_type, + const uint8_t *random_addr); + +/* Calculate the amount of time in microseconds a PDU with payload length of + * 'payload_len' will take to transmit on a PHY 'phy_mode'. */ +uint32_t ble_ll_pdu_tx_time_get(uint16_t payload_len, int phy_mode); + +/* Calculate maximum octets of PDU payload which can be transmitted during + * 'usecs' on a PHY 'phy_mode'. */ +uint16_t ble_ll_pdu_max_tx_octets_get(uint32_t usecs, int phy_mode); + +/* Is this address a resolvable private address? */ +int ble_ll_is_rpa(const uint8_t *addr, uint8_t addr_type); + +int ble_ll_addr_subtype(const uint8_t *addr, uint8_t addr_type); + +/* Is this address an identity address? */ +int ble_ll_addr_is_id(uint8_t *addr, uint8_t addr_type); + +/* Is 'addr' our device address? 'addr_type' is public (0) or random (!=0) */ +int ble_ll_is_our_devaddr(uint8_t *addr, int addr_type); + +/* Get identity address 'addr_type' is public (0) or random (!=0) */ +uint8_t *ble_ll_get_our_devaddr(uint8_t addr_type); + +/** + * Called to put a packet on the Link Layer transmit packet queue. + * + * @param txpdu Pointer to transmit packet + */ +void ble_ll_acl_data_in(struct os_mbuf *txpkt); + +/** + * Allocates mbuf for received PDU + * + * This allocated mbuf (may be chained if necessary) that has capacity large + * enough to store received PDU of given length. It does not set mbufs length + * as this has to be done by PHY when copying data. + * + * @param len Length of PDU, including PDU header and excluding MIC (if encrypted) + * + * @return mbuf large enough to store received PDU on success + * NULL on failure (oom) + */ +struct os_mbuf *ble_ll_rxpdu_alloc(uint16_t len); + +/* Tell the Link Layer there has been a data buffer overflow */ +void ble_ll_data_buffer_overflow(void); + +/* Tell the link layer there has been a hardware error */ +void ble_ll_hw_error(void); + +/*--- PHY interfaces ---*/ +struct ble_mbuf_hdr; + +/* Called by the PHY when a packet has started */ +int ble_ll_rx_start(uint8_t *rxbuf, uint8_t chan, struct ble_mbuf_hdr *hdr); + +/* Called by the PHY when a packet reception ends */ +int ble_ll_rx_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr); + +/* Helper callback to tx mbuf using ble_phy_tx() */ +uint8_t ble_ll_tx_mbuf_pducb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte); +uint8_t ble_ll_tx_flat_mbuf_pducb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte); + +/*--- Controller API ---*/ +void ble_ll_mbuf_init(struct os_mbuf *m, uint8_t pdulen, uint8_t hdr); + +/* Set the link layer state */ +void ble_ll_state_set(uint8_t ll_state); + +/* Get the link layer state */ +uint8_t ble_ll_state_get(void); + +/* Send an event to LL task */ +void ble_ll_event_send(struct ble_npl_event *ev); + +/* Hand received pdu's to LL task */ +void ble_ll_rx_pdu_in(struct os_mbuf *rxpdu); + +/* + * Set public address + * + * This can be used to set controller public address from vendor specific storage, + * usually should be done in hal_bsp_init(). + * Shall be *only* called before LL is initialized, i.e. before sysinit stage. + */ +int ble_ll_set_public_addr(const uint8_t *addr); + +/* Set random address */ +int ble_ll_set_random_addr(const uint8_t *cmdbuf, uint8_t len, bool hci_adv_ext); + +/* Wait for response timer expiration callback */ +void ble_ll_wfr_timer_exp(void *arg); + +/* Read set of features supported by the Link Layer */ +uint64_t ble_ll_read_supp_features(void); + +/* Set host supported features */ +int ble_ll_set_host_feat(const uint8_t *cmdbuf, uint8_t len); + +/* Read set of states supported by the Link Layer */ +uint64_t ble_ll_read_supp_states(void); + +/* Check if octets and time are valid. Returns 0 if not valid */ +int ble_ll_chk_txrx_octets(uint16_t octets); +int ble_ll_chk_txrx_time(uint16_t time); + +/* Random numbers */ +int ble_ll_rand_init(void); +void ble_ll_rand_sample(uint8_t rnum); +int ble_ll_rand_data_get(uint8_t *buf, uint8_t len); +void ble_ll_rand_prand_get(uint8_t *prand); +int ble_ll_rand_start(void); + +static inline int +ble_ll_get_addr_type(uint8_t txrxflag) +{ + if (txrxflag) { + return BLE_HCI_ADV_OWN_ADDR_RANDOM; + } + return BLE_HCI_ADV_OWN_ADDR_PUBLIC; +} + +/* Convert usecs to ticks and round up to nearest tick */ +static inline uint32_t +ble_ll_usecs_to_ticks_round_up(uint32_t usecs) +{ + return os_cputime_usecs_to_ticks(usecs + 30); +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) +/* LTK 0x4C68384139F574D836BCF34E9DFB01BF */ +extern const uint8_t g_bletest_LTK[]; +extern uint16_t g_bletest_EDIV; +extern uint64_t g_bletest_RAND; +extern uint64_t g_bletest_SKDm; +extern uint64_t g_bletest_SKDs; +extern uint32_t g_bletest_IVm; +extern uint32_t g_bletest_IVs; +#endif + +#if MYNEWT_VAL(BLE_LL_DTM) +void ble_ll_dtm_init(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* H_LL_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_adv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_adv.h new file mode 100644 index 000000000..eee07cbf0 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_adv.h @@ -0,0 +1,209 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_LL_ADV_ +#define H_BLE_LL_ADV_ + +#include "nimble/porting/nimble/include/syscfg/syscfg.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * ADV event timing + * T_advEvent = advInterval + advDelay + * + * advInterval: increments of 625 usecs + * advDelay: RAND[0, 10] msecs + * + */ +#define BLE_LL_ADV_ITVL (625) /* usecs */ +#define BLE_LL_ADV_ITVL_MIN (32) /* units */ +#define BLE_LL_ADV_ITVL_MAX (16384) /* units */ +#define BLE_LL_ADV_ITVL_MS_MIN (20) /* msecs */ +#define BLE_LL_ADV_ITVL_MS_MAX (10240) /* msecs */ +#define BLE_LL_ADV_ITVL_SCAN_MIN (160) /* units */ +#define BLE_LL_ADV_ITVL_SCAN_MS_MIN (100) /* msecs */ +#define BLE_LL_ADV_ITVL_NONCONN_MS_MIN (100) /* msecs */ +#define BLE_LL_ADV_DELAY_MS_MIN (0) /* msecs */ +#define BLE_LL_ADV_DELAY_MS_MAX (10) /* msecs */ +#define BLE_LL_ADV_PDU_ITVL_LD_MS_MAX (10) /* msecs */ +#define BLE_LL_ADV_PDU_ITVL_HD_MS_MAX (3750) /* usecs */ +#define BLE_LL_ADV_STATE_HD_MAX (1280) /* msecs */ +#define BLE_LL_ADV_PERIODIC_ITVL (1250) /* usecs */ + +/* Maximum advertisement data length */ +#define BLE_ADV_LEGACY_DATA_MAX_LEN (31) +#define BLE_ADV_LEGACY_MAX_PKT_LEN (37) + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +#define BLE_ADV_DATA_MAX_LEN MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE) +#else +#define BLE_ADV_DATA_MAX_LEN BLE_ADV_LEGACY_DATA_MAX_LEN +#endif + +/* + * ADV_IND + * -> AdvA (6 bytes) + * -> AdvData (0 - 31 bytes) + * + * The advertising address (AdvA) is a public address (TxAdd=0) or random + * address (TxAdd = 1) + */ +#define BLE_ADV_IND_MIN_LEN (6) +#define BLE_ADV_IND_MAX_LEN (37) + +/* + * ADV_DIRECT_IND + * -> AdvA (6 bytes) + * -> InitA (6 bytes) + * + * AdvA is the advertisers public address (TxAdd=0) or random address + * (TxAdd = 1). + * + * InitA is the initiators public or random address. This is the address + * to which this packet is addressed. + * + */ +#define BLE_ADV_DIRECT_IND_LEN (12) + +/* + * ADV_NONCONN_IND + * -> AdvA (6 bytes) + * -> AdvData (0 - 31 bytes) + * + * The advertising address (AdvA) is a public address (TxAdd=0) or random + * address (TxAdd = 1) + * + */ +#define BLE_ADV_NONCONN_IND_MIN_LEN (6) +#define BLE_ADV_NONCONN_IND_MAX_LEN (37) + +/* + * ADV_SCAN_IND + * -> AdvA (6 bytes) + * -> AdvData (0 - 31 bytes) + * + * The advertising address (AdvA) is a public address (TxAdd=0) or random + * address (TxAdd = 1) + * + */ +#define BLE_ADV_SCAN_IND_MIN_LEN (6) +#define BLE_ADV_SCAN_IND_MAX_LEN (37) + +/*---- HCI ----*/ +struct ble_ll_adv_sm; +struct ble_ll_conn_sm; + +/* Start an advertiser */ +int ble_ll_adv_start_req(uint8_t adv_chanmask, uint8_t adv_type, + uint8_t *init_addr, uint16_t adv_itvl, void *handle); + +/* Start or stop advertising */ +int ble_ll_hci_adv_set_enable(const uint8_t *cmdbuf, uint8_t len); + +/* Set legacy advertising data */ +int ble_ll_hci_set_adv_data(const uint8_t *cmdbuf, uint8_t len); + +/* Set scan response data */ +int ble_ll_hci_set_scan_rsp_data(const uint8_t *cmd, uint8_t cmd_len); + +/* Set advertising parameters */ +int ble_ll_adv_set_adv_params(const uint8_t *cmdbuf, uint8_t len); + +/* Read advertising channel power */ +int ble_ll_adv_read_txpwr(uint8_t *rspbuf, uint8_t *rsplen); + +/*---- API used by BLE LL ----*/ +/* Send the connection complete event */ +void ble_ll_adv_send_conn_comp_ev(struct ble_ll_conn_sm *connsm, + struct ble_mbuf_hdr *rxhdr); + +/* Returns local resolvable private address */ +uint8_t *ble_ll_adv_get_local_rpa(struct ble_ll_adv_sm *advsm); + +/* Returns peer resolvable private address */ +uint8_t *ble_ll_adv_get_peer_rpa(struct ble_ll_adv_sm *advsm); + +/* Called to initialize advertising functionality. */ +void ble_ll_adv_init(void); + +/* Called when LL wait for response timer expires in advertising state */ +void ble_ll_adv_wfr_timer_exp(void); + +/* Called to reset the advertiser. */ +void ble_ll_adv_reset(void); + +/* Called on rx pdu start when in advertising state */ +int ble_ll_adv_rx_isr_start(uint8_t pdu_type); + +/* Called on rx pdu end when in advertising state */ +int ble_ll_adv_rx_isr_end(uint8_t pdu_type, struct os_mbuf *rxpdu, int crcok); + +/* Processes received packets at the link layer task */ +void ble_ll_adv_rx_pkt_in(uint8_t ptype, uint8_t *rxbuf, + struct ble_mbuf_hdr *hdr); + +/* Boolean function denoting whether or not the whitelist can be changed */ +int ble_ll_adv_can_chg_whitelist(void); + +/* + * Called when an advertising event has been removed from the scheduler + * without being run. + */ +void ble_ll_adv_event_rmvd_from_sched(struct ble_ll_adv_sm *advsm); + +/* + * Called when a periodic event has been removed from the scheduler + * without being run. + */ +void ble_ll_adv_periodic_rmvd_from_sched(struct ble_ll_adv_sm *advsm); + +/* Called to halt currently running advertising event */ +void ble_ll_adv_halt(void); + +/* Called to determine if advertising is enabled */ +uint8_t ble_ll_adv_enabled(void); + +int ble_ll_adv_hci_set_random_addr(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_adv_set_random_addr(const uint8_t *addr, uint8_t instance); +int ble_ll_adv_remove(const uint8_t *addr, uint8_t len); +int ble_ll_adv_clear_all(void); +int ble_ll_adv_ext_set_param(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen); +int ble_ll_adv_ext_set_adv_data(const uint8_t *cmdbuf, uint8_t cmdlen); +int ble_ll_adv_ext_set_scan_rsp(const uint8_t *cmdbuf, uint8_t cmdlen); +int ble_ll_adv_ext_set_enable(const uint8_t *cmdbuf, uint8_t len); + +int ble_ll_adv_periodic_set_param(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_adv_periodic_set_data(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_adv_periodic_enable(const uint8_t *cmdbuf, uint8_t len); + +int ble_ll_adv_periodic_set_info_transfer(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen); + +/* Called to notify adv code about RPA rotation */ +void ble_ll_adv_rpa_timeout(void); + +#ifdef __cplusplus +} +#endif + +#endif /* H_BLE_LL_ADV_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_conn.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_conn.h new file mode 100644 index 000000000..178d67117 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_conn.h @@ -0,0 +1,425 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_LL_CONN_ +#define H_BLE_LL_CONN_ + +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/include/nimble/hci_common.h" +#include "nimble/nimble/include/nimble/nimble_npl.h" +#include "ble_ll_sched.h" +#include "ble_ll_ctrl.h" +#include "ble_phy.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Roles */ +#define BLE_LL_CONN_ROLE_NONE (0) +#define BLE_LL_CONN_ROLE_MASTER (1) +#define BLE_LL_CONN_ROLE_SLAVE (2) + +/* Connection states */ +#define BLE_LL_CONN_STATE_IDLE (0) +#define BLE_LL_CONN_STATE_CREATED (1) +#define BLE_LL_CONN_STATE_ESTABLISHED (2) + +/* Channel map size */ +#define BLE_LL_CONN_CHMAP_LEN (5) + +/* Definitions for source clock accuracy */ +#define BLE_MASTER_SCA_251_500_PPM (0) +#define BLE_MASTER_SCA_151_250_PPM (1) +#define BLE_MASTER_SCA_101_150_PPM (2) +#define BLE_MASTER_SCA_76_100_PPM (3) +#define BLE_MASTER_SCA_51_75_PPM (4) +#define BLE_MASTER_SCA_31_50_PPM (5) +#define BLE_MASTER_SCA_21_30_PPM (6) +#define BLE_MASTER_SCA_0_20_PPM (7) + +/* Definition for RSSI when the RSSI is unknown */ +#define BLE_LL_CONN_UNKNOWN_RSSI (127) + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) +/* + * Encryption states for a connection + * + * NOTE: the states are ordered so that we can check to see if the state + * is greater than ENCRYPTED. If so, it means that the start or pause + * encryption procedure is running and we should not send data pdu's. + */ +enum conn_enc_state { + CONN_ENC_S_UNENCRYPTED = 1, + CONN_ENC_S_ENCRYPTED, + CONN_ENC_S_ENC_RSP_WAIT, + CONN_ENC_S_PAUSE_ENC_RSP_WAIT, + CONN_ENC_S_PAUSED, + CONN_ENC_S_START_ENC_REQ_WAIT, + CONN_ENC_S_START_ENC_RSP_WAIT, + CONN_ENC_S_LTK_REQ_WAIT, + CONN_ENC_S_LTK_NEG_REPLY +}; + +/* + * Note that the LTK is the key, the SDK is the plain text, and the + * session key is the cipher text portion of the encryption block. + * + * NOTE: we have intentionally violated the specification by making the + * transmit and receive packet counters 32-bits as opposed to 39 (as per the + * specification). We do this to save code space, ram and calculation time. The + * only drawback is that any encrypted connection that sends more than 2^32 + * packets will suffer a MIC failure and thus be disconnected. + */ +struct ble_ll_conn_enc_data +{ + uint8_t enc_state; + uint8_t tx_encrypted; + uint16_t enc_div; + uint32_t tx_pkt_cntr; + uint32_t rx_pkt_cntr; + uint64_t host_rand_num; + uint8_t iv[8]; + struct ble_encryption_block enc_block; +}; +#endif + +/* Connection state machine flags. */ +union ble_ll_conn_sm_flags { + struct { + uint32_t pkt_rxd:1; + uint32_t terminate_ind_txd:1; + uint32_t terminate_ind_rxd:1; + uint32_t terminate_ind_rxd_acked:1; + uint32_t allow_slave_latency:1; + uint32_t slave_set_last_anchor:1; + uint32_t awaiting_host_reply:1; + uint32_t terminate_started:1; + uint32_t conn_update_sched:1; + uint32_t host_expects_upd_event:1; + uint32_t version_ind_sent:1; + uint32_t rxd_version_ind:1; + uint32_t chanmap_update_scheduled:1; + uint32_t conn_empty_pdu_txd:1; + uint32_t last_txd_md:1; + uint32_t conn_req_txd:1; + uint32_t send_ltk_req:1; + uint32_t encrypted:1; + uint32_t encrypt_chg_sent:1; + uint32_t le_ping_supp:1; + uint32_t csa2_supp:1; + uint32_t host_phy_update: 1; + uint32_t phy_update_sched: 1; + uint32_t ctrlr_phy_update: 1; + uint32_t phy_update_event: 1; + uint32_t peer_phy_update: 1; /* XXX:combine with ctrlr udpate bit? */ + uint32_t aux_conn_req: 1; + uint32_t rxd_features:1; + uint32_t pending_hci_rd_features:1; + uint32_t pending_initiate_dle:1; + } cfbit; + uint32_t conn_flags; +} __attribute__((packed)); + +/** + * Structure used for PHY data inside a connection. + * + * NOTE: the new phy's are the phys we will change to when a phy update + * procedure is ongoing and the event counter hits the instant. + * + * tx_phy_mode: chip specific phy mode for tx + * rx_phy_mode: chip specific phy mode for rx + * cur_tx_phy: value denoting current tx_phy (not a bitmask!) + * cur_rx_phy: value denoting current rx phy (not a bitmask!) + * new_tx_phy: value denoting new tx_phy (not a bitmask!) + * new_rx_phy: value denoting new rx phy (not a bitmask!) + * req_pref_tx_phy: tx phy sent in a phy request (may be different than host) + * req_pref_rx_phy: rx phy sent in a phy request (may be different than host) + * host_pref_tx_phys: bitmask of preferred transmit PHYs sent by host + * host_pref_rx_phys: bitmask of preferred receive PHYs sent by host + * phy_options: preferred phy options for coded phy + */ +struct ble_ll_conn_phy_data +{ + uint32_t tx_phy_mode: 2; + uint32_t rx_phy_mode: 2; + uint32_t cur_tx_phy: 2; + uint32_t cur_rx_phy: 2; + uint32_t new_tx_phy: 2; + uint32_t new_rx_phy: 2; + uint32_t host_pref_tx_phys_mask: 3; + uint32_t host_pref_rx_phys_mask: 3; + uint32_t req_pref_tx_phys_mask: 3; + uint32_t req_pref_rx_phys_mask: 3; + uint32_t phy_options: 2; +} __attribute__((packed)); + +#define CONN_CUR_TX_PHY_MASK(csm) (1 << ((csm)->phy_data.cur_tx_phy - 1)) +#define CONN_CUR_RX_PHY_MASK(csm) (1 << ((csm)->phy_data.cur_rx_phy - 1)) + +struct hci_conn_update +{ + uint16_t handle; + uint16_t conn_itvl_min; + uint16_t conn_itvl_max; + uint16_t conn_latency; + uint16_t supervision_timeout; + uint16_t min_ce_len; + uint16_t max_ce_len; +}; + +struct hci_ext_conn_params +{ + uint16_t scan_itvl; + uint16_t scan_window; + uint16_t conn_itvl_min; + uint16_t conn_itvl_max; + uint16_t conn_latency; + uint16_t supervision_timeout; + uint16_t min_ce_len; + uint16_t max_ce_len; +}; + +struct hci_ext_create_conn +{ + uint8_t filter_policy; + uint8_t own_addr_type; + uint8_t peer_addr_type; + uint8_t peer_addr[BLE_DEV_ADDR_LEN]; + uint8_t init_phy_mask; + struct hci_ext_conn_params params[3]; +}; + +/* Connection state machine */ +struct ble_ll_conn_sm +{ + /* Connection state machine flags */ + union ble_ll_conn_sm_flags csmflags; + + /* Current connection handle, state and role */ + uint16_t conn_handle; + uint8_t conn_state; + uint8_t conn_role; /* Can possibly be 1 bit */ + + /* RSSI */ + int8_t conn_rssi; + + /* For privacy */ + int8_t rpa_index; + + /* Connection data length management */ + uint8_t max_tx_octets; + uint8_t max_rx_octets; + uint8_t rem_max_tx_octets; + uint8_t rem_max_rx_octets; + uint8_t eff_max_tx_octets; + uint8_t eff_max_rx_octets; + uint16_t max_tx_time; + uint16_t max_rx_time; + uint16_t rem_max_tx_time; + uint16_t rem_max_rx_time; + uint16_t eff_max_tx_time; + uint16_t eff_max_rx_time; + uint8_t max_tx_octets_phy_mode[BLE_PHY_NUM_MODE]; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + uint16_t host_req_max_tx_time; +#endif + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + struct ble_ll_conn_phy_data phy_data; + uint16_t phy_instant; + uint8_t phy_tx_transition; +#endif + + /* Used to calculate data channel index for connection */ + uint8_t chanmap[BLE_LL_CONN_CHMAP_LEN]; + uint8_t req_chanmap[BLE_LL_CONN_CHMAP_LEN]; + uint16_t chanmap_instant; + uint16_t channel_id; /* TODO could be union with hop and last chan used */ + uint8_t hop_inc; + uint8_t data_chan_index; + uint8_t last_unmapped_chan; + uint8_t num_used_chans; + +#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING) + uint8_t period_occ_mask; /* mask: period 0 = 0x01, period 3 = 0x08 */ +#endif + + /* Ack/Flow Control */ + uint8_t tx_seqnum; /* note: can be 1 bit */ + uint8_t next_exp_seqnum; /* note: can be 1 bit */ + uint8_t cons_rxd_bad_crc; /* note: can be 1 bit */ + uint8_t last_rxd_sn; /* note: cant be 1 bit given current code */ + uint8_t last_rxd_hdr_byte; /* note: possibly can make 1 bit since we + only use the MD bit now */ + + /* connection event mgmt */ + uint8_t reject_reason; + uint8_t host_reply_opcode; + uint8_t master_sca; + uint8_t tx_win_size; + uint8_t cur_ctrl_proc; + uint8_t disconnect_reason; + uint8_t rxd_disconnect_reason; + uint8_t vers_nr; + uint8_t conn_features; + uint8_t remote_features[7]; + uint16_t pending_ctrl_procs; + uint16_t event_cntr; + uint16_t completed_pkts; + uint16_t comp_id; + uint16_t sub_vers_nr; + uint16_t auth_pyld_tmo; /* could be ifdef'd. 10 msec units */ + + uint32_t access_addr; + uint32_t crcinit; /* only low 24 bits used */ + /* XXX: do we need ce_end_time? Cant this be sched end time? */ + uint32_t ce_end_time; /* cputime at which connection event should end */ + uint32_t terminate_timeout; + uint32_t last_scheduled; + + /* Connection timing */ + uint16_t conn_itvl; + uint16_t slave_latency; + uint16_t supervision_tmo; + uint16_t min_ce_len; + uint16_t max_ce_len; + uint16_t tx_win_off; + uint32_t anchor_point; + uint8_t anchor_point_usecs; /* XXX: can this be uint8_t ?*/ + uint8_t conn_itvl_usecs; + uint32_t conn_itvl_ticks; + uint32_t last_anchor_point; /* Slave only */ + uint32_t slave_cur_tx_win_usecs; + uint32_t slave_cur_window_widening; + uint32_t last_rxd_pdu_cputime; /* Used exclusively for supervision timer */ + + /* + * Used to mark that identity address was used as InitA + */ + uint8_t inita_identity_used; + + /* address information */ + uint8_t own_addr_type; + uint8_t peer_addr_type; + uint8_t peer_addr[BLE_DEV_ADDR_LEN]; + + /* + * XXX: TODO. Could save memory. Have single event at LL and put these + * on a singly linked list. Only would need list pointer here. + */ + /* Connection end event */ + struct ble_npl_event conn_ev_end; + + /* Packet transmit queue */ + struct os_mbuf *cur_tx_pdu; + STAILQ_HEAD(conn_txq_head, os_mbuf_pkthdr) conn_txq; + + /* List entry for active/free connection pools */ + union { + SLIST_ENTRY(ble_ll_conn_sm) act_sle; + STAILQ_ENTRY(ble_ll_conn_sm) free_stqe; + }; + + /* LL control procedure response timer */ + struct ble_npl_callout ctrl_proc_rsp_timer; + + /* For scheduling connections */ + struct ble_ll_sched_item conn_sch; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) + struct ble_npl_callout auth_pyld_timer; +#endif + + /* + * XXX: a note on all these structures for control procedures. First off, + * all of these need to be ifdef'd to save memory. Another thing to + * consider is this: since most control procedures can only run when no + * others are running, can I use just one structure (a union)? Should I + * allocate these from a pool? Not sure what to do. For now, I just use + * a large chunk of memory per connection. + */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + struct ble_ll_conn_enc_data enc_data; +#endif + /* + * For connection update procedure. XXX: can make this a pointer and + * malloc it if we want to save space. + */ + struct hci_conn_update conn_param_req; + + /* For connection update procedure */ + struct ble_ll_conn_upd_req conn_update_req; + + /* XXX: for now, just store them all */ + struct ble_ll_conn_params conn_cp; + + struct ble_ll_scan_sm *scansm; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + struct hci_ext_create_conn initial_params; +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) + uint8_t sync_transfer_mode; + uint16_t sync_transfer_skip; + uint32_t sync_transfer_sync_timeout; +#endif +}; + +/* Flags */ +#define CONN_F_UPDATE_SCHED(csm) ((csm)->csmflags.cfbit.conn_update_sched) +#define CONN_F_EMPTY_PDU_TXD(csm) ((csm)->csmflags.cfbit.conn_empty_pdu_txd) +#define CONN_F_LAST_TXD_MD(csm) ((csm)->csmflags.cfbit.last_txd_md) +#define CONN_F_CONN_REQ_TXD(csm) ((csm)->csmflags.cfbit.conn_req_txd) +#define CONN_F_ENCRYPTED(csm) ((csm)->csmflags.cfbit.encrypted) +#define CONN_F_ENC_CHANGE_SENT(csm) ((csm)->csmflags.cfbit.encrypt_chg_sent) +#define CONN_F_LE_PING_SUPP(csm) ((csm)->csmflags.cfbit.le_ping_supp) +#define CONN_F_TERMINATE_STARTED(csm) ((csm)->csmflags.cfbit.terminate_started) +#define CONN_F_CSA2_SUPP(csm) ((csm)->csmflags.cfbit.csa2_supp) +#define CONN_F_HOST_PHY_UPDATE(csm) ((csm)->csmflags.cfbit.host_phy_update) +#define CONN_F_PHY_UPDATE_SCHED(csm) ((csm)->csmflags.cfbit.phy_update_sched) +#define CONN_F_CTRLR_PHY_UPDATE(csm) ((csm)->csmflags.cfbit.ctrlr_phy_update) +#define CONN_F_PHY_UPDATE_EVENT(csm) ((csm)->csmflags.cfbit.phy_update_event) +#define CONN_F_PEER_PHY_UPDATE(csm) ((csm)->csmflags.cfbit.peer_phy_update) +#define CONN_F_AUX_CONN_REQ(csm) ((csm)->csmflags.cfbit.aux_conn_req) + +/* Role */ +#define CONN_IS_MASTER(csm) (csm->conn_role == BLE_LL_CONN_ROLE_MASTER) +#define CONN_IS_SLAVE(csm) (csm->conn_role == BLE_LL_CONN_ROLE_SLAVE) + +/* + * Given a handle, returns an active connection state machine (or NULL if the + * handle does not exist + * + */ +struct ble_ll_conn_sm *ble_ll_conn_find_active_conn(uint16_t handle); + +/* required for unit testing */ +uint8_t ble_ll_conn_calc_dci(struct ble_ll_conn_sm *conn, uint16_t latency); + +/* used to get anchor point for connection event specified */ +void ble_ll_conn_get_anchor(struct ble_ll_conn_sm *connsm, uint16_t conn_event, + uint32_t *anchor, uint8_t *anchor_usecs); + +#ifdef __cplusplus +} +#endif + +#endif /* H_BLE_LL_CONN_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_ctrl.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_ctrl.h new file mode 100644 index 000000000..b0da1e736 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_ctrl.h @@ -0,0 +1,313 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_LL_CTRL_ +#define H_BLE_LL_CTRL_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * LL control procedures. This "enumeration" is not in the specification; + * It is used to determine which LL control procedure is currently running + * in a connection and which ones may be pending. + */ +#define BLE_LL_CTRL_PROC_CONN_UPDATE (0) +#define BLE_LL_CTRL_PROC_CHAN_MAP_UPD (1) +#define BLE_LL_CTRL_PROC_ENCRYPT (2) +#define BLE_LL_CTRL_PROC_FEATURE_XCHG (3) +#define BLE_LL_CTRL_PROC_VERSION_XCHG (4) +#define BLE_LL_CTRL_PROC_TERMINATE (5) +#define BLE_LL_CTRL_PROC_CONN_PARAM_REQ (6) +#define BLE_LL_CTRL_PROC_LE_PING (7) +#define BLE_LL_CTRL_PROC_DATA_LEN_UPD (8) +#define BLE_LL_CTRL_PROC_PHY_UPDATE (9) +#define BLE_LL_CTRL_PROC_NUM (10) +#define BLE_LL_CTRL_PROC_IDLE (255) + +/* Checks if a particular control procedure is running */ +#define IS_PENDING_CTRL_PROC(sm, proc) (sm->pending_ctrl_procs & (1 << proc)) +#define CLR_PENDING_CTRL_PROC(sm, proc) (sm->pending_ctrl_procs &= ~(1 << proc)) + +/* LL control procedure timeout */ +#define BLE_LL_CTRL_PROC_TIMEOUT_MS (40000) /* ms */ + +/* + * LL CTRL PDU format + * -> Opcode (1 byte) + * -> Data (0 - 26 bytes) + */ +#define BLE_LL_CTRL_CONN_UPDATE_IND (0) +#define BLE_LL_CTRL_CHANNEL_MAP_REQ (1) +#define BLE_LL_CTRL_TERMINATE_IND (2) +#define BLE_LL_CTRL_ENC_REQ (3) +#define BLE_LL_CTRL_ENC_RSP (4) +#define BLE_LL_CTRL_START_ENC_REQ (5) +#define BLE_LL_CTRL_START_ENC_RSP (6) +#define BLE_LL_CTRL_UNKNOWN_RSP (7) +#define BLE_LL_CTRL_FEATURE_REQ (8) +#define BLE_LL_CTRL_FEATURE_RSP (9) +#define BLE_LL_CTRL_PAUSE_ENC_REQ (10) +#define BLE_LL_CTRL_PAUSE_ENC_RSP (11) +#define BLE_LL_CTRL_VERSION_IND (12) +#define BLE_LL_CTRL_REJECT_IND (13) +#define BLE_LL_CTRL_SLAVE_FEATURE_REQ (14) +#define BLE_LL_CTRL_CONN_PARM_REQ (15) +#define BLE_LL_CTRL_CONN_PARM_RSP (16) +#define BLE_LL_CTRL_REJECT_IND_EXT (17) +#define BLE_LL_CTRL_PING_REQ (18) +#define BLE_LL_CTRL_PING_RSP (19) +#define BLE_LL_CTRL_LENGTH_REQ (20) +#define BLE_LL_CTRL_LENGTH_RSP (21) +#define BLE_LL_CTRL_PHY_REQ (22) +#define BLE_LL_CTRL_PHY_RSP (23) +#define BLE_LL_CTRL_PHY_UPDATE_IND (24) +#define BLE_LL_CTRL_MIN_USED_CHAN_IND (25) +#define BLE_LL_CTRL_CTE_REQ (26) +#define BLE_LL_CTRL_CTE_RSP (27) +#define BLE_LL_CTRL_PERIODIC_SYNC_IND (28) +#define BLE_LL_CTRL_CLOCK_ACCURACY_REQ (29) +#define BLE_LL_CTRL_CLOCK_ACCURACY_RSP (30) + +/* Maximum opcode value */ +#define BLE_LL_CTRL_OPCODES (BLE_LL_CTRL_CLOCK_ACCURACY_RSP + 1) + +extern const uint8_t g_ble_ll_ctrl_pkt_lengths[BLE_LL_CTRL_OPCODES]; + +/* Maximum LL control PDU size */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) +#define BLE_LL_CTRL_MAX_PDU_LEN (35) +#else +#define BLE_LL_CTRL_MAX_PDU_LEN (27) +#endif + +/* LL control connection update request */ +struct ble_ll_conn_upd_req +{ + uint8_t winsize; + uint16_t winoffset; + uint16_t interval; + uint16_t latency; + uint16_t timeout; + uint16_t instant; +}; +#define BLE_LL_CTRL_CONN_UPD_REQ_LEN (11) + +/* LL control channel map request */ +struct ble_ll_chan_map_req +{ + uint8_t chmap[5]; + uint16_t instant; +}; +#define BLE_LL_CTRL_CHAN_MAP_LEN (7) + +/* + * LL control terminate ind + * -> error code (1 byte) + */ +#define BLE_LL_CTRL_TERMINATE_IND_LEN (1) + +/* LL control enc req */ +struct ble_ll_enc_req +{ + uint8_t rand[8]; + uint16_t ediv; + uint8_t skdm[8]; + uint32_t ivm; +}; + +#define BLE_LL_CTRL_ENC_REQ_LEN (22) + +/* LL control enc rsp */ +struct ble_ll_enc_rsp +{ + uint8_t skds[8]; + uint32_t ivs; +}; + +#define BLE_LL_CTRL_ENC_RSP_LEN (12) + +/* LL control start/pause enc request and response */ +#define BLE_LL_CTRL_START_ENC_REQ_LEN (0) +#define BLE_LL_CTRL_START_ENC_RSP_LEN (0) +#define BLE_LL_CTRL_PAUSE_ENC_REQ_LEN (0) +#define BLE_LL_CTRL_PAUSE_ENC_RSP_LEN (0) + +/* + * LL control unknown response + * -> 1 byte which contains the unknown or un-supported opcode. + */ +#define BLE_LL_CTRL_UNK_RSP_LEN (1) + +/* + * LL control feature req and LL control feature rsp + * -> 8 bytes of data containing features supported by device. + */ +#define BLE_LL_CTRL_FEATURE_LEN (8) + +/* + * LL control version ind + * -> version (1 byte): + * Contains the version number of the bluetooth controller specification. + * -> comp_id (2 bytes) + * Contains the company identifier of the manufacturer of the controller. + * -> sub_ver_num: Contains a unique value for implementation or revision of + * the bluetooth controller. + */ +struct ble_ll_version_ind +{ + uint8_t ble_ctrlr_ver; + uint16_t company_id; + uint16_t sub_ver_num; +}; + +#define BLE_LL_CTRL_VERSION_IND_LEN (5) + +/* + * LL control reject ind + * -> error code (1 byte): contains reason why request was rejected. + */ +#define BLE_LL_CTRL_REJ_IND_LEN (1) + +/* + * LL control slave feature req + * -> 8 bytes of data containing features supported by device. + */ +#define BLE_LL_CTRL_SLAVE_FEATURE_REQ_LEN (8) + +/* LL control connection param req and connection param rsp */ +struct ble_ll_conn_params +{ + uint16_t interval_min; + uint16_t interval_max; + uint16_t latency; + uint16_t timeout; + uint8_t pref_periodicity; + uint16_t ref_conn_event_cnt; + uint16_t offset0; + uint16_t offset1; + uint16_t offset2; + uint16_t offset3; + uint16_t offset4; + uint16_t offset5; +}; + +#define BLE_LL_CTRL_CONN_PARAMS_LEN (23) + +/* LL control reject ind ext */ +struct ble_ll_reject_ind_ext +{ + uint8_t reject_opcode; + uint8_t err_code; +}; + +#define BLE_LL_CTRL_REJECT_IND_EXT_LEN (2) + +/* LL control ping req and ping rsp (contain no data) */ +#define BLE_LL_CTRL_PING_LEN (0) + +/* + * LL control length req and length rsp + * -> max_rx_bytes (2 bytes): defines connMaxRxOctets. Range 27 to 251 + * -> max_rx_time (2 bytes): defines connMaxRxTime. Range 328 to 2120 usecs. + * -> max_tx_bytes (2 bytes): defines connMaxTxOctets. Range 27 to 251 + * -> max_tx_time (2 bytes): defines connMaxTxTime. Range 328 to 2120 usecs. + */ +struct ble_ll_len_req +{ + uint16_t max_rx_bytes; + uint16_t max_rx_time; + uint16_t max_tx_bytes; + uint16_t max_tx_time; +}; + +#define BLE_LL_CTRL_LENGTH_REQ_LEN (8) + +/* PHY request/response */ +#define BLE_LL_CTRL_PHY_REQ_LEN (2) +#define BLE_LL_CTRL_PHY_RSP_LEN (2) +#define BLE_LL_CTRL_PHY_UPD_IND_LEN (4) + +/* Min used channels */ +#define BLE_LL_CTRL_MIN_USED_CHAN_LEN (2) + +/* CTE REQ */ +#define BLE_LL_CTRL_CTE_REQ_LEN (1) + +/* CTE RSP (contains no data) */ +#define BLE_LL_CTRL_CTE_RSP_LEN (0) + +/* Periodic Sync Transfer IND */ +#define BLE_LL_CTRL_PERIODIC_SYNC_IND_LEN (34) + +/* Clock accuracy request/response */ +#define BLE_LL_CTRL_CLOCK_ACCURACY_REQ_LEN (1) +#define BLE_LL_CTRL_CLOCK_ACCURACY_RSP_LEN (1) + +/* API */ +struct ble_ll_conn_sm; +void ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc); +void ble_ll_ctrl_proc_stop(struct ble_ll_conn_sm *connsm, int ctrl_proc); +int ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om); +void ble_ll_ctrl_chk_proc_start(struct ble_ll_conn_sm *connsm); +void ble_ll_ctrl_terminate_start(struct ble_ll_conn_sm *connsm); +int ble_ll_ctrl_is_terminate_ind(uint8_t hdr, uint8_t opcode); +uint8_t ble_ll_ctrl_conn_param_reply(struct ble_ll_conn_sm *connsm, + uint8_t *rsp, + struct ble_ll_conn_params *req); +int ble_ll_ctrl_reject_ind_send(struct ble_ll_conn_sm *connsm, + uint8_t rej_opcode, uint8_t err); +int ble_ll_ctrl_start_enc_send(struct ble_ll_conn_sm *connsm); +int ble_ll_ctrl_enc_allowed_pdu_rx(struct os_mbuf *rxpdu); +int ble_ll_ctrl_enc_allowed_pdu_tx(struct os_mbuf_pkthdr *pkthdr); +int ble_ll_ctrl_tx_done(struct os_mbuf *txpdu, struct ble_ll_conn_sm *connsm); +int ble_ll_ctrl_is_start_enc_rsp(struct os_mbuf *txpdu); + +void ble_ll_hci_ev_datalen_chg(struct ble_ll_conn_sm *connsm); +void ble_ll_hci_ev_rem_conn_parm_req(struct ble_ll_conn_sm *connsm, + struct ble_ll_conn_params *cp); +void ble_ll_hci_ev_conn_update(struct ble_ll_conn_sm *connsm, uint8_t status); +void ble_ll_hci_ev_rd_rem_used_feat(struct ble_ll_conn_sm *connsm, + uint8_t status); +void ble_ll_hci_ev_rd_rem_ver(struct ble_ll_conn_sm *connsm, uint8_t status); +void ble_ll_hci_ev_encrypt_chg(struct ble_ll_conn_sm *connsm, uint8_t status); +int ble_ll_hci_ev_ltk_req(struct ble_ll_conn_sm *connsm); +int ble_ll_hci_ev_hw_err(uint8_t hw_err); +void ble_ll_hci_ev_databuf_overflow(void); +void ble_ll_hci_ev_le_csa(struct ble_ll_conn_sm *connsm); +void ble_ll_hci_ev_send_scan_req_recv(uint8_t adv_handle, const uint8_t *peer, + uint8_t peer_addr_type); +void ble_ll_hci_ev_send_scan_timeout(void); +void ble_ll_hci_ev_send_adv_set_terminated(uint8_t status, uint8_t adv_handle, + uint16_t conn_handle, uint8_t events); +int ble_ll_hci_ev_phy_update(struct ble_ll_conn_sm *connsm, uint8_t status); +void ble_ll_calc_session_key(struct ble_ll_conn_sm *connsm); +void ble_ll_ctrl_phy_update_proc_complete(struct ble_ll_conn_sm *connsm); +void ble_ll_ctrl_initiate_dle(struct ble_ll_conn_sm *connsm); +void ble_ll_hci_ev_send_vendor_err(const char *file, uint32_t line); + +uint8_t ble_ll_ctrl_phy_tx_transition_get(uint8_t phy_mask); +uint8_t ble_ll_ctrl_phy_from_phy_mask(uint8_t phy_mask); + +#ifdef __cplusplus +} +#endif + +#endif /* H_BLE_LL_CTRL_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_hci.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_hci.h new file mode 100644 index 000000000..5806f6737 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_hci.h @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_LL_HCI_ +#define H_BLE_LL_HCI_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nimble/nimble/include/nimble/hci_common.h" + +/* For supported commands */ +#define BLE_LL_SUPP_CMD_LEN (42) +extern const uint8_t g_ble_ll_supp_cmds[BLE_LL_SUPP_CMD_LEN]; + +/* The largest event the controller will send. */ +#define BLE_LL_MAX_EVT_LEN MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE) + +/* + * This determines the number of outstanding commands allowed from the + * host to the controller. NOTE: you cannot change this without modifying + * other portions of the code as we currently use a global os event for + * the command; you would need to allocate a pool of these. + */ +#define BLE_LL_CFG_NUM_HCI_CMD_PKTS (1) + +typedef void (*ble_ll_hci_post_cmd_complete_cb)(void); + +/* Initialize LL HCI */ +void ble_ll_hci_init(void); + +/* Used to determine if the LE event is enabled/disabled */ +bool ble_ll_hci_is_le_event_enabled(unsigned int subev); + +/* Used to determine if event is enabled/disabled */ +bool ble_ll_hci_is_event_enabled(unsigned int evcode); + +/* Send event from controller to host */ +int ble_ll_hci_event_send(struct ble_hci_ev *hci_ev); + +/* Sends a command complete with a no-op opcode to host */ +void ble_ll_hci_send_noop(void); + +/* Checks the preferref phy masks from set default phy and set phy commands */ +int ble_ll_hci_chk_phy_masks(uint8_t all_phys, uint8_t tx_phys, uint8_t rx_phys, + uint8_t *txphy, uint8_t *rxphy); + +/* Returns true if Extended Advertising HCI commands are in use */ +bool ble_ll_hci_adv_mode_ext(void); + +/* Get TX power compensation rounded to integer dB */ +int8_t ble_ll_get_tx_pwr_compensation(void); + +#ifdef __cplusplus +} +#endif + +#endif /* H_BLE_LL_HCI_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_resolv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_resolv.h new file mode 100644 index 000000000..228e0a370 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_resolv.h @@ -0,0 +1,116 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_LL_RESOLV_ +#define H_BLE_LL_RESOLV_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * An entry in the resolving list. + * The identity address is stored in little endian format. + * The local rpa is stored in little endian format. + * The IRKs are stored in big endian format. + * + * Note: + * rl_local_irk and rl_peer_irk need to be word aligned + */ +struct ble_ll_resolv_entry +{ + uint8_t rl_addr_type; + uint8_t rl_priv_mode; + uint8_t rl_has_local; + uint8_t rl_has_peer; + uint8_t rl_local_irk[16]; + uint8_t rl_peer_irk[16]; + uint8_t rl_identity_addr[BLE_DEV_ADDR_LEN]; + uint8_t rl_local_rpa[BLE_DEV_ADDR_LEN]; + uint8_t rl_peer_rpa[BLE_DEV_ADDR_LEN]; +}; + +extern struct ble_ll_resolv_entry g_ble_ll_resolv_list[]; + +/* Clear the resolving list */ +int ble_ll_resolv_list_clr(void); + +/* Read the size of the resolving list */ +int ble_ll_resolv_list_read_size(uint8_t *rspbuf, uint8_t *rsplen); + +/* Add a device to the resolving list */ +int ble_ll_resolv_list_add(const uint8_t *cmdbuf, uint8_t len); + +/* Remove a device from the resolving list */ +int ble_ll_resolv_list_rmv(const uint8_t *cmdbuf, uint8_t len); + +/* Address resolution enable command */ +int ble_ll_resolv_enable_cmd(const uint8_t *cmdbuf, uint8_t len); + +int ble_ll_resolv_peer_addr_rd(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen); +int ble_ll_resolv_local_addr_rd(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen); + +/* Finds 'addr' in resolving list. Doesnt check if address resolution enabled */ +struct ble_ll_resolv_entry * +ble_ll_resolv_list_find(const uint8_t *addr, uint8_t addr_type); + +/* Returns true if address resolution is enabled */ +uint8_t ble_ll_resolv_enabled(void); + +/* Reset private address resolution */ +void ble_ll_resolv_list_reset(void); + +/* Generate local or peer RPA. It is up to caller to make sure required IRK + * is present on RL + */ +void ble_ll_resolv_get_priv_addr(struct ble_ll_resolv_entry *rl, int local, + uint8_t *addr); + +void ble_ll_resolv_set_peer_rpa(int index, uint8_t *rpa); +void ble_ll_resolv_set_local_rpa(int index, uint8_t *rpa); + +/* Generate a resolvable private address. */ +int ble_ll_resolv_gen_rpa(uint8_t *addr, uint8_t addr_type, uint8_t *rpa, + int local); + +/* Set the resolvable private address timeout */ +int ble_ll_resolv_set_rpa_tmo(const uint8_t *cmdbuf, uint8_t len); + +/* Set the privacy mode */ +int ble_ll_resolve_set_priv_mode(const uint8_t *cmdbuf, uint8_t len); + +/* Get the RPA timeout, in seconds */ +uint32_t ble_ll_resolv_get_rpa_tmo(void); + +/* Resolve a resolvable private address */ +int ble_ll_resolv_rpa(const uint8_t *rpa, const uint8_t *irk); + +/* Try to resolve peer RPA and return index on RL if matched */ +int ble_ll_resolv_peer_rpa_any(const uint8_t *rpa); + +/* Initialize resolv*/ +void ble_ll_resolv_init(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_rfmgmt.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_rfmgmt.h new file mode 100644 index 000000000..37b81a88b --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_rfmgmt.h @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_LL_RFMGMT_ +#define H_BLE_LL_RFMGMT_ + +#ifdef __cplusplus +extern "C" { +#endif + +void ble_ll_rfmgmt_init(void); + +#if MYNEWT_VAL(BLE_LL_RFMGMT_ENABLE_TIME) > 0 + +void ble_ll_rfmgmt_reset(void); + +/* Notify rfmgmt that scan window has changed (only called from ble_ll_scan) */ +void ble_ll_rfmgmt_scan_changed(bool enabled, uint32_t next_window); + +/* Notify rfmgmt that 1st scheduled item has changed (only called from ble_ll_sched) */ +void ble_ll_rfmgmt_sched_changed(struct ble_ll_sched_item *first); + +/* Notify rfmgmt that RF is no longer needed by current event */ +void ble_ll_rfmgmt_release(void); + +/* Enables RF immediately and returns tick at which RF will be fully enabled */ +uint32_t ble_ll_rfmgmt_enable_now(void); + +/* Returns true only if RF is currently fully enabled (i.e. not off or enabling) */ +bool ble_ll_rfmgmt_is_enabled(void); + +#else + +static inline void ble_ll_rfmgmt_reset(void) { } +static inline void ble_ll_rfmgmt_scan_changed(bool e, uint32_t n) { } +static inline void ble_ll_rfmgmt_sched_changed(struct ble_ll_sched_item *f) { } +static inline void ble_ll_rfmgmt_release(void) { } +static inline uint32_t ble_ll_rfmgmt_enable_now(void) { return 0; } +static inline bool ble_ll_rfmgmt_is_enabled(void) { return true; } + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* H_BLE_LL_RFMGMT_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_scan.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_scan.h new file mode 100644 index 000000000..ca50824d0 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_scan.h @@ -0,0 +1,293 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_LL_SCAN_ +#define H_BLE_LL_SCAN_ + +#include "ble_ll_sched.h" +#include "nimble/porting/nimble/include/hal/hal_timer.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/nimble/include/nimble/nimble_npl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * SCAN_REQ + * -> ScanA (6 bytes) + * -> AdvA (6 bytes) + * + * ScanA is the scanners public (TxAdd=0) or random (TxAdd = 1) address + * AdvaA is the advertisers public (RxAdd=0) or random (RxAdd=1) address. + * + * Sent by the LL in the Scanning state; received by the LL in the advertising + * state. The advertising address is the intended recipient of this frame. + */ +#define BLE_SCAN_REQ_LEN (12) + +/* + * SCAN_RSP + * -> AdvA (6 bytes) + * -> ScanRspData (0 - 31 bytes) + * + * AdvaA is the advertisers public (TxAdd=0) or random (TxAdd=1) address. + * ScanRspData may contain any data from the advertisers host. + * + * Sent by the LL in the advertising state; received by the LL in the + * scanning state. + */ +#define BLE_SCAN_RSP_LEGACY_DATA_MAX_LEN (31) +#define BLE_SCAN_LEGACY_MAX_PKT_LEN (37) + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +#define BLE_SCAN_RSP_DATA_MAX_LEN MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE) + +/* For Bluetooth 5.0 we need state machine for two PHYs*/ +#define BLE_LL_SCAN_PHY_NUMBER (2) +#else +#define BLE_LL_SCAN_PHY_NUMBER (1) +#define BLE_SCAN_RSP_DATA_MAX_LEN BLE_SCAN_RSP_LEGACY_DATA_MAX_LEN +#endif + +#define PHY_UNCODED (0) +#define PHY_CODED (1) + +#define BLE_LL_EXT_ADV_MODE_NON_CONN (0x00) +#define BLE_LL_EXT_ADV_MODE_CONN (0x01) +#define BLE_LL_EXT_ADV_MODE_SCAN (0x02) + +/* All values are stored as ticks */ +struct ble_ll_scan_timing { + uint32_t interval; + uint32_t window; + uint32_t start_time; +}; + +struct ble_ll_scan_params +{ + uint8_t phy; + uint8_t own_addr_type; + uint8_t scan_filt_policy; + uint8_t configured; + uint8_t scan_type; + uint8_t scan_chan; + struct ble_ll_scan_timing timing; +}; + +#define BLE_LL_AUX_HAS_ADVA 0x01 +#define BLE_LL_AUX_HAS_TARGETA 0x02 +#define BLE_LL_AUX_HAS_ADI 0x04 +#define BLE_LL_AUX_IS_MATCHED 0x08 +#define BLE_LL_AUX_IS_TARGETA_RESOLVED 0x10 + +#define BLE_LL_AUX_FLAG_HCI_SENT_ANY 0x02 +#define BLE_LL_AUX_FLAG_HCI_SENT_COMPLETED 0x04 +#define BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED 0x08 +#define BLE_LL_AUX_FLAG_SCAN_COMPLETE 0x10 +#define BLE_LL_AUX_FLAG_SCAN_ERROR 0x20 +#define BLE_LL_AUX_FLAG_AUX_ADV_RECEIVED 0x40 +#define BLE_LL_AUX_FLAG_AUX_CHAIN_RECEIVED 0x80 + +struct ble_ll_aux_data { + uint8_t flags; + + /* + * Since aux_data can be accessed from ISR and LL, we have separate copies + * of flags to make sure that ISR does not modify flags while LL uses them. + * ISR updates 'flags_isr' and LL adds these to 'flags_ll' which it then + * uses for further processing allowing to update 'flags_isr' if another + * scan for given 'aux_data' is scheduled. Note that flags must not be unset + * while aux_data is valid. + */ + uint8_t flags_isr; + uint8_t flags_ll; + + uint8_t ref_cnt; + uint8_t chan; + uint8_t aux_phy; + uint8_t aux_primary_phy; + uint8_t mode; + uint8_t scanning; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + int8_t rpa_index; +#endif + uint16_t adi; + uint32_t offset; + uint8_t offset_units; + uint8_t adva[6]; + uint8_t adva_type; + uint8_t targeta[6]; + uint8_t targeta_type; + uint16_t evt_type; + struct ble_ll_sched_item sch; + struct ble_hci_ev *evt; + struct ble_npl_event ev; +}; + +struct ble_ll_scan_pdu_data { + uint8_t hdr_byte; + /* ScanA for SCAN_REQ and InitA for CONNECT_IND */ + union { + uint8_t scana[BLE_DEV_ADDR_LEN]; + uint8_t inita[BLE_DEV_ADDR_LEN]; + }; + uint8_t adva[BLE_DEV_ADDR_LEN]; +}; + +struct ble_ll_scan_sm +{ + uint8_t scan_enabled; + uint8_t own_addr_type; + uint8_t scan_filt_dups; + uint8_t scan_rsp_pending; + uint8_t scan_rsp_cons_fails; + uint8_t scan_rsp_cons_ok; + uint8_t scan_peer_rpa[BLE_DEV_ADDR_LEN]; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + ble_npl_time_t scan_nrpa_timer; + uint8_t scan_nrpa[BLE_DEV_ADDR_LEN]; +#endif + struct ble_ll_scan_pdu_data pdu_data; + + /* XXX: Shall we count backoff per phy? */ + uint16_t upper_limit; + uint16_t backoff_count; + uint32_t scan_win_start_time; + struct ble_npl_event scan_sched_ev; + struct hal_timer scan_timer; + struct ble_npl_event scan_interrupted_ev; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + struct hal_timer duration_timer; + struct hal_timer period_timer; + uint32_t duration_ticks; + uint32_t period_ticks; + uint8_t ext_scanning; +#endif + + uint8_t restart_timer_needed; + struct ble_ll_aux_data *cur_aux_data; + + struct ble_ll_scan_params *scanp; + struct ble_ll_scan_params *scanp_next; + struct ble_ll_scan_params scanp_phys[BLE_LL_SCAN_PHY_NUMBER]; +}; + +/* Scan types */ +#define BLE_SCAN_TYPE_PASSIVE (BLE_HCI_SCAN_TYPE_PASSIVE) +#define BLE_SCAN_TYPE_ACTIVE (BLE_HCI_SCAN_TYPE_ACTIVE) +#define BLE_SCAN_TYPE_INITIATE (2) + +/*---- HCI ----*/ +/* Set scanning parameters */ +int ble_ll_scan_set_scan_params(const uint8_t *cmdbuf, uint8_t len); + +/* Turn scanning on/off */ +int ble_ll_hci_scan_set_enable(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_hci_ext_scan_set_enable(const uint8_t *cmdbuf, uint8_t len); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +int ble_ll_set_ext_scan_params(const uint8_t *cmdbuf, uint8_t len); +#endif + +/*--- Controller Internal API ---*/ +/* Initialize the scanner */ +void ble_ll_scan_init(void); + +/* Reset the scanner */ +void ble_ll_scan_reset(void); + +/* Called when Link Layer starts to receive a PDU and is in scanning state */ +int ble_ll_scan_rx_isr_start(uint8_t pdu_type, uint16_t *rxflags); + +/* Called when Link Layer has finished receiving a PDU while scanning */ +int ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok); + +/* Process a scan response PDU */ +void ble_ll_scan_rx_pkt_in(uint8_t pdu_type, struct os_mbuf *om, + struct ble_mbuf_hdr *hdr); + +/* Boolean function denoting whether or not the whitelist can be changed */ +int ble_ll_scan_can_chg_whitelist(void); + +/* Boolean function returning true if scanning enabled */ +int ble_ll_scan_enabled(void); + +/* Boolean function returns true if whitelist is enabled for scanning */ +int ble_ll_scan_whitelist_enabled(void); + +/* Initialize the scanner when we start initiating */ +struct hci_create_conn; +int ble_ll_scan_initiator_start(struct hci_create_conn *hcc, + struct ble_ll_scan_sm **sm); + +/* Returns storage for PDU data (for SCAN_REQ or CONNECT_IND) */ +struct ble_ll_scan_pdu_data *ble_ll_scan_get_pdu_data(void); + +/* Called to set the resolvable private address of the last connected peer */ +void ble_ll_scan_set_peer_rpa(uint8_t *rpa); + +/* Returns peer RPA of last connection made */ +uint8_t *ble_ll_scan_get_peer_rpa(void); + +/* Returns the local RPA used by the scanner/initiator */ +uint8_t *ble_ll_scan_get_local_rpa(void); + +/* Stop the scanning state machine */ +void ble_ll_scan_sm_stop(int chk_disable); + +/* Resume scanning */ +void ble_ll_scan_chk_resume(void); + +/* Called when wait for response timer expires in scanning mode */ +void ble_ll_scan_wfr_timer_exp(void); + +/* Called when scan could be interrupted */ +void ble_ll_scan_interrupted(struct ble_ll_scan_sm *scansm); + +int ble_ll_scan_adv_decode_addr(uint8_t pdu_type, uint8_t *rxbuf, + struct ble_mbuf_hdr *ble_hdr, + uint8_t **addr, uint8_t *addr_type, + uint8_t **inita, uint8_t *init_addr_type, + int *ext_mode); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +int ble_ll_scan_update_aux_data(struct ble_mbuf_hdr *ble_hdr, uint8_t *rxbuf, + bool *adva_present); + +/* Initialize the extended scanner when we start initiating */ +struct hci_ext_create_conn; +int ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc, + struct ble_ll_scan_sm **sm); + +/* Called to parse extended advertising*/ +struct ble_ll_aux_data *ble_ll_scan_aux_data_ref(struct ble_ll_aux_data *aux_scan); +void ble_ll_scan_aux_data_unref(struct ble_ll_aux_data *aux_scan); +void ble_ll_scan_end_adv_evt(struct ble_ll_aux_data *aux_data); +#endif + +/* Called to halt currently running scan */ +void ble_ll_scan_halt(void); + +#ifdef __cplusplus +} +#endif + +#endif /* H_BLE_LL_SCAN_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_sched.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_sched.h new file mode 100644 index 000000000..a614cf090 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_sched.h @@ -0,0 +1,216 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_LL_SCHED_ +#define H_BLE_LL_SCHED_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Time per BLE scheduler slot */ +#define BLE_LL_SCHED_USECS_PER_SLOT (1250) +#define BLE_LL_SCHED_32KHZ_TICKS_PER_SLOT (41) /* 1 tick = 30.517 usecs */ + +/* + * Worst case time needed for scheduled advertising item. This is the longest + * possible time to receive a scan request and send a scan response (with the + * appropriate IFS time between them). This number is calculated using the + * following formula: IFS + SCAN_REQ + IFS + SCAN_RSP = 150 + 176 + 150 + 376. + * Note: worst case time to tx adv, rx scan req and send scan rsp is 1228 usecs. + * This assumes maximum sized advertising PDU and scan response PDU. + * + * For connectable advertising events no scan request is allowed. In this case + * we just need to receive a connect request PDU: IFS + CONNECT_REQ = 150 + 352. + * Note: worst-case is 376 + 150 + 352 = 878 usecs + * + * NOTE: The advertising PDU transmit time is NOT included here since we know + * how long that will take (worst-case is 376 usecs). + */ +#define BLE_LL_SCHED_ADV_MAX_USECS (852) +#define BLE_LL_SCHED_DIRECT_ADV_MAX_USECS (502) +#define BLE_LL_SCHED_MAX_ADV_PDU_USECS (376) + +/* + * This is the offset from the start of the scheduled item until the actual + * tx/rx should occur, in ticks. + */ +extern uint8_t g_ble_ll_sched_offset_ticks; + +/* + * This is the number of slots needed to transmit and receive a maximum + * size PDU, including an IFS time before each. The actual time is + * 2120 usecs for tx/rx and 150 for IFS = 4540 usecs. + */ +#define BLE_LL_SCHED_MAX_TXRX_SLOT (4 * BLE_LL_SCHED_USECS_PER_SLOT) + +/* BLE scheduler errors */ +#define BLE_LL_SCHED_ERR_OVERLAP (1) + +/* Types of scheduler events */ +#define BLE_LL_SCHED_TYPE_ADV (1) +#define BLE_LL_SCHED_TYPE_SCAN (2) +#define BLE_LL_SCHED_TYPE_CONN (3) +#define BLE_LL_SCHED_TYPE_AUX_SCAN (4) +#define BLE_LL_SCHED_TYPE_DTM (5) +#define BLE_LL_SCHED_TYPE_PERIODIC (6) +#define BLE_LL_SCHED_TYPE_SYNC (7) + +/* Return values for schedule callback. */ +#define BLE_LL_SCHED_STATE_RUNNING (0) +#define BLE_LL_SCHED_STATE_DONE (1) + +/* Callback function */ +struct ble_ll_sched_item; +typedef int (*sched_cb_func)(struct ble_ll_sched_item *sch); +typedef void (*sched_remove_cb_func)(struct ble_ll_sched_item *sch); +/* + * Strict connection scheduling (for the master) is different than how + * connections are normally scheduled. With strict connection scheduling we + * introduce the concept of a "period". A period is a collection of slots. Each + * slot is 1.25 msecs in length. The number of slots in a period is determined + * by the syscfg value BLE_LL_CONN_INIT_SLOTS. A collection of periods is called + * an epoch. The length of an epoch is determined by the number of connections + * (BLE_MAX_CONNECTIONS plus BLE_LL_ADD_STRICT_SCHED_PERIODS). Connections + * will be scheduled at period boundaries. Any scanning/initiating/advertising + * will be done in unused periods, if possible. + */ +#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING) +#define BLE_LL_SCHED_PERIODS (MYNEWT_VAL(BLE_MAX_CONNECTIONS) + \ + MYNEWT_VAL(BLE_LL_ADD_STRICT_SCHED_PERIODS)) + +struct ble_ll_sched_obj +{ + uint8_t sch_num_occ_periods; + uint32_t sch_occ_period_mask; + uint32_t sch_ticks_per_period; + uint32_t sch_ticks_per_epoch; + uint32_t sch_epoch_start; +}; + +extern struct ble_ll_sched_obj g_ble_ll_sched_data; + +/* + * XXX: TODO: + * -> How do we know epoch start is up to date? Not wrapped? + * -> for now, only do this with no more than 32 connections. + * -> Do not let initiating occur if no empty sched slots + */ +#endif + +/* + * Schedule item + * sched_type: This is the type of the schedule item. + * enqueued: Flag denoting if item is on the scheduler list. 0: no, 1:yes + * remainder: # of usecs from offset till tx/rx should occur + * txrx_offset: Number of ticks from start time until tx/rx should occur. + * + */ +struct ble_ll_sched_item +{ + uint8_t sched_type; + uint8_t enqueued; + uint8_t remainder; + uint32_t start_time; + uint32_t end_time; + void *cb_arg; + sched_cb_func sched_cb; + TAILQ_ENTRY(ble_ll_sched_item) link; +}; + +/* Initialize the scheduler */ +int ble_ll_sched_init(void); + +/* Remove item(s) from schedule */ +int ble_ll_sched_rmv_elem(struct ble_ll_sched_item *sch); + +void ble_ll_sched_rmv_elem_type(uint8_t type, sched_remove_cb_func remove_cb); + +/* Schedule a new master connection */ +struct ble_ll_conn_sm; +int ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm, + struct ble_mbuf_hdr *ble_hdr, uint8_t pyld_len); + +/* Schedule a new slave connection */ +int ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm); + +struct ble_ll_adv_sm; +typedef void ble_ll_sched_adv_new_cb(struct ble_ll_adv_sm *advsm, + uint32_t sch_start, void *arg); + +/* Schedule a new advertising event */ +int ble_ll_sched_adv_new(struct ble_ll_sched_item *sch, + ble_ll_sched_adv_new_cb cb, void *arg); + +/* Schedule periodic advertising event */ +int ble_ll_sched_periodic_adv(struct ble_ll_sched_item *sch, uint32_t *start, + bool after_overlap); + +int ble_ll_sched_sync_reschedule(struct ble_ll_sched_item *sch, + uint32_t anchor_point, + uint8_t anchor_point_usecs, + uint32_t window_widening, int8_t phy_mode); +int ble_ll_sched_sync(struct ble_ll_sched_item *sch, + uint32_t beg_cputime, uint32_t rem_usecs, uint32_t offset, + int8_t phy_mode); + +/* Reschedule an advertising event */ +int ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t *start, + uint32_t max_delay_ticks); + +/* Reschedule and advertising pdu */ +int ble_ll_sched_adv_resched_pdu(struct ble_ll_sched_item *sch); + +/* Reschedule a connection that had previously been scheduled or that is over */ +int ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm * connsm); + +/** + * Called to determine when the next scheduled event will occur. + * + * If there are not scheduled events this function returns 0; otherwise it + * returns 1 and *next_event_time is set to the start time of the next event. + * + * @param next_event_time cputime at which next scheduled event will occur + * + * @return int 0: No events are scheduled 1: there is an upcoming event + */ +int ble_ll_sched_next_time(uint32_t *next_event_time); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +struct ble_ll_scan_sm; +struct ble_ll_aux_data; +int ble_ll_sched_aux_scan(struct ble_mbuf_hdr *ble_hdr, + struct ble_ll_scan_sm *scansm, + struct ble_ll_aux_data *aux_scan); + +int ble_ll_sched_scan_req_over_aux_ptr(uint32_t chan, uint8_t phy_mode); +#endif + +/* Stop the scheduler */ +void ble_ll_sched_stop(void); + +#if MYNEWT_VAL(BLE_LL_DTM) +int ble_ll_sched_dtm(struct ble_ll_sched_item *sch); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* H_LL_SCHED_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_sync.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_sync.h new file mode 100644 index 000000000..96c52a92a --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_sync.h @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_LL_SYNC_ +#define H_BLE_LL_SYNC_ + +#include + +#include "nimble/nimble/include/nimble/ble.h" +#include "ble_ll_hci.h" +#include "ble_ll_conn.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct ble_ll_sync_sm; + +int ble_ll_sync_create(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_sync_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb); +int ble_ll_sync_terminate(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_sync_list_add(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_sync_list_remove(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_sync_list_clear(void); +int ble_ll_sync_list_size(uint8_t *rspbuf, uint8_t *rsplen); +int ble_ll_sync_receive_enable(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_sync_transfer(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen); + +void ble_ll_sync_periodic_ind(struct ble_ll_conn_sm *connsm, + const uint8_t *sync_ind, bool reports_disabled, + uint16_t max_skip, uint32_t sync_timeout); +void ble_ll_sync_transfer_disconnected(struct ble_ll_conn_sm *connsm); + +void ble_ll_sync_info_event(const uint8_t *addr, uint8_t addr_type, + int rpa_index, uint8_t sid, + struct ble_mbuf_hdr *rxhdr, + const uint8_t *syncinfo); + +int ble_ll_sync_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *rxhdr); +int ble_ll_sync_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr); +void ble_ll_sync_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr); +void ble_ll_sync_wfr_timer_exp(void); +void ble_ll_sync_halt(void); +void ble_ll_sync_rmvd_from_sched(struct ble_ll_sync_sm *sm); + +uint32_t ble_ll_sync_get_event_end_time(void); + +bool ble_ll_sync_enabled(void); + +void ble_ll_sync_reset(void); +void ble_ll_sync_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* H_BLE_LL_SYNC_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_test.h similarity index 90% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_test.h index a2d328756..32984c6b3 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_test.h @@ -17,14 +17,16 @@ * under the License. */ -#ifndef H_BLE_HS_STARTUP_ -#define H_BLE_HS_STARTUP_ +#ifndef H_LL_TEST_ +#define H_LL_TEST_ + +#include #ifdef __cplusplus extern "C" { #endif -int ble_hs_startup_go(void); +int ble_ll_csa2_test_all(void); #ifdef __cplusplus } diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_trace.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_trace.h new file mode 100644 index 000000000..f0af4de50 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_trace.h @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_LL_TRACE_ +#define H_BLE_LL_TRACE_ + +#include "nimble/porting/nimble/include/os/os_trace_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BLE_LL_TRACE_ID_SCHED 0 +#define BLE_LL_TRACE_ID_RX_START 1 +#define BLE_LL_TRACE_ID_RX_END 2 +#define BLE_LL_TRACE_ID_WFR_EXP 3 +#define BLE_LL_TRACE_ID_CTRL_RX 4 +#define BLE_LL_TRACE_ID_CONN_EV_START 5 +#define BLE_LL_TRACE_ID_CONN_EV_END 6 +#define BLE_LL_TRACE_ID_CONN_END 7 +#define BLE_LL_TRACE_ID_CONN_TX 8 +#define BLE_LL_TRACE_ID_CONN_RX 9 +#define BLE_LL_TRACE_ID_ADV_TXDONE 10 +#define BLE_LL_TRACE_ID_ADV_HALT 11 +#define BLE_LL_TRACE_ID_AUX_REF 12 +#define BLE_LL_TRACE_ID_AUX_UNREF 13 + +#if MYNEWT_VAL(BLE_LL_SYSVIEW) + +extern uint32_t ble_ll_trace_off; + +void ble_ll_trace_init(void); + +static inline void +ble_ll_trace_u32(unsigned id, uint32_t p1) +{ + os_trace_api_u32(ble_ll_trace_off + id, p1); +} + +static inline void +ble_ll_trace_u32x2(unsigned id, uint32_t p1, uint32_t p2) +{ + os_trace_api_u32x2(ble_ll_trace_off + id, p1, p2); +} + +static inline void +ble_ll_trace_u32x3(unsigned id, uint32_t p1, uint32_t p2, uint32_t p3) +{ + os_trace_api_u32x3(ble_ll_trace_off + id, p1, p2, p3); +} + +#else + +static inline void +ble_ll_trace_init(void) +{ +} + +static inline void +ble_ll_trace_u32(unsigned id, uint32_t p1) +{ +} + +static inline void +ble_ll_trace_u32x2(unsigned id, uint32_t p1, uint32_t p2) +{ +} + +static inline void +ble_ll_trace_u32x3(unsigned id, uint32_t p1, uint32_t p2, uint32_t p3) +{ +} + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* H_BLE_LL_TRACE_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_utils.h similarity index 58% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_utils.h index 8923678a3..248309009 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_utils.h @@ -17,22 +17,13 @@ * under the License. */ -#ifndef H_BLE_HS_MBUF_PRIV_ -#define H_BLE_HS_MBUF_PRIV_ +#include -#ifdef __cplusplus -extern "C" { -#endif - -struct os_mbuf; - -struct os_mbuf *ble_hs_mbuf_bare_pkt(void); -struct os_mbuf *ble_hs_mbuf_acl_pkt(void); -struct os_mbuf *ble_hs_mbuf_l2cap_pkt(void); -int ble_hs_mbuf_pullup_base(struct os_mbuf **om, int base_len); - -#ifdef __cplusplus -} -#endif - -#endif +uint32_t ble_ll_utils_calc_access_addr(void); +uint8_t ble_ll_utils_remapped_channel(uint8_t remap_index, const uint8_t *chanmap); +uint8_t ble_ll_utils_calc_dci_csa2(uint16_t event_cntr, uint16_t channel_id, + uint8_t num_used_chans, const uint8_t *chanmap); +uint8_t ble_ll_utils_calc_num_used_chans(const uint8_t *chanmap); +uint32_t ble_ll_utils_calc_window_widening(uint32_t anchor_point, + uint32_t last_anchor_point, + uint8_t master_sca); diff --git a/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/include/nimble/nimble_port.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_whitelist.h similarity index 54% rename from lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/include/nimble/nimble_port.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_whitelist.h index fe9592764..2d3b6c5dd 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/include/nimble/nimble_port.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_whitelist.h @@ -17,32 +17,36 @@ * under the License. */ -#ifndef _NIMBLE_PORT_H -#define _NIMBLE_PORT_H - -#include "nimble/nimble_npl.h" - -#define NIMBLE_CORE (CONFIG_BT_NIMBLE_PINNED_TO_CORE < portNUM_PROCESSORS ? CONFIG_BT_NIMBLE_PINNED_TO_CORE : tskNO_AFFINITY) -#define NIMBLE_STACK_SIZE CONFIG_BT_NIMBLE_TASK_STACK_SIZE +#ifndef H_BLE_LL_WHITELIST_ +#define H_BLE_LL_WHITELIST_ #ifdef __cplusplus extern "C" { #endif -void nimble_port_init(void); -void nimble_port_deinit(void); +/* Clear the whitelist */ +int ble_ll_whitelist_clear(void); -void nimble_port_run(void); -int nimble_port_stop(void); +/* Read the size of the whitelist */ +int ble_ll_whitelist_read_size(uint8_t *rspbuf, uint8_t *rsplen); -struct ble_npl_eventq *nimble_port_get_dflt_eventq(void); +/* Add a device to the whitelist */ +int ble_ll_whitelist_add(const uint8_t *cmdbuf, uint8_t len); -#if NIMBLE_CFG_CONTROLLER -void nimble_port_ll_task_func(void *arg); -#endif +/* Remove a device fromthe whitelist */ +int ble_ll_whitelist_rmv(const uint8_t *cmdbuf, uint8_t len); + +/* Enable whitelisting */ +void ble_ll_whitelist_enable(void); + +/* Disable whitelisting */ +void ble_ll_whitelist_disable(void); + +/* Boolean function returning true if address matches a whitelist entry */ +int ble_ll_whitelist_match(uint8_t *addr, uint8_t addr_type, int is_ident); #ifdef __cplusplus } #endif -#endif /* _NIMBLE_PORT_H */ +#endif /* H_BLE_LL_WHITELIST_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_phy.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_phy.h new file mode 100644 index 000000000..8a6fd174e --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_phy.h @@ -0,0 +1,242 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_PHY_ +#define H_BLE_PHY_ + +#include "nimble/nimble/include/nimble/hci_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Forward declarations */ +struct os_mbuf; + +/* Channel/Frequency defintions */ +#define BLE_PHY_NUM_CHANS (40) +#define BLE_PHY_NUM_DATA_CHANS (37) +#define BLE_PHY_CHAN0_FREQ_MHZ (2402) +#define BLE_PHY_DATA_CHAN0_FREQ_MHZ (2404) +#define BLE_PHY_CHAN_SPACING_MHZ (2) +#define BLE_PHY_NUM_ADV_CHANS (3) +#define BLE_PHY_ADV_CHAN_START (37) + +/* Power */ +#define BLE_PHY_MAX_PWR_DBM (10) + +/* Deviation */ +#define BLE_PHY_DEV_KHZ (185) +#define BLE_PHY_BINARY_ZERO (-BLE_PHY_DEV) +#define BLE_PHY_BINARY_ONE (BLE_PHY_DEV) + +/* Max. clock drift */ +#define BLE_PHY_MAX_DRIFT_PPM (50) + +/* Data rate */ +#define BLE_PHY_BIT_RATE_BPS (1000000) + +/* Macros */ +#define BLE_IS_ADV_CHAN(chan) (chan >= BLE_PHY_ADV_CHAN_START) +#define BLE_IS_DATA_CHAN(chan) (chan < BLE_PHY_ADV_CHAN_START) + +/* PHY states */ +#define BLE_PHY_STATE_IDLE (0) +#define BLE_PHY_STATE_RX (1) +#define BLE_PHY_STATE_TX (2) + +/* BLE PHY transitions */ +#define BLE_PHY_TRANSITION_NONE (0) +#define BLE_PHY_TRANSITION_RX_TX (1) +#define BLE_PHY_TRANSITION_TX_RX (2) + +/* PHY error codes */ +#define BLE_PHY_ERR_RADIO_STATE (1) +#define BLE_PHY_ERR_INIT (2) +#define BLE_PHY_ERR_INV_PARAM (3) +#define BLE_PHY_ERR_NO_BUFS (4) +#define BLE_PHY_ERR_TX_LATE (5) +#define BLE_PHY_ERR_RX_LATE (6) + +/* Maximun PDU length. Includes LL header of 2 bytes and 255 bytes payload. */ +#define BLE_PHY_MAX_PDU_LEN (257) + +/* Wait for response timer */ +typedef void (*ble_phy_tx_end_func)(void *arg); + +/* Initialize the PHY */ +int ble_phy_init(void); + +/* Reset the PHY */ +int ble_phy_reset(void); + +/* Set the PHY channel */ +int ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit); + +/* Set transmit start time */ +int ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs); + +/* Set receive start time */ +int ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs); + +/* Set the transmit end callback and argument */ +void ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg); + +typedef uint8_t (*ble_phy_tx_pducb_t)(uint8_t *dptr, void *pducb_arg, + uint8_t *hdr_byte); + +/* Place the PHY into transmit mode */ +int ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans); + +/* Place the PHY into receive mode */ +int ble_phy_rx(void); + +/* Copies the received PHY buffer into the allocated pdu */ +void ble_phy_rxpdu_copy(uint8_t *dptr, struct os_mbuf *rxpdu); + +/* Set the transmit power */ +int ble_phy_txpwr_set(int dbm); + +/* Get highest allowed power from range */ +int ble_phy_txpower_round(int dbm); + +/* Get the transmit power */ +int ble_phy_txpwr_get(void); + +/* Set RX path power compensation value rounded to integer dB */ +void ble_phy_set_rx_pwr_compensation(int8_t compensation); + +/* Disable the PHY */ +void ble_phy_disable(void); + +#define BLE_PHY_WFR_ENABLE_RX (0) +#define BLE_PHY_WFR_ENABLE_TXRX (1) + +void ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs); + +/* Starts rf clock */ +void ble_phy_rfclk_enable(void); + +/* Stops rf clock */ +void ble_phy_rfclk_disable(void); + +/* + * Used to restart reception on same channel after wfr timer expiration or + * frame received. + */ +void ble_phy_restart_rx(void); + +/* Gets the current state of the PHY */ +int ble_phy_state_get(void); + +/* Gets current state of transceiver */ +uint8_t ble_phy_xcvr_state_get(void); + +/* Returns 'true' if a reception has started */ +int ble_phy_rx_started(void); + +/* + * Returns the maximum supported tx/rx PDU payload size, in bytes, for data + * channel PDUs (this does not apply to advertising channel PDUs). Note + * that the data channel PDU is composed of a 2-byte header, the payload, and + * an optional MIC. The maximum payload is 251 bytes. + */ +uint8_t ble_phy_max_data_pdu_pyld(void); + +/* Gets the current access address */ +uint32_t ble_phy_access_addr_get(void); + +/* Enable encryption */ +void ble_phy_encrypt_enable(uint64_t pkt_counter, uint8_t *iv, uint8_t *key, + uint8_t is_master); + +/* Disable encryption */ +void ble_phy_encrypt_disable(void); + +/* Set the packet counters and dir used by LE encyption */ +void ble_phy_encrypt_set_pkt_cntr(uint64_t pkt_counter, int dir); + +/* Enable phy resolving list */ +void ble_phy_resolv_list_enable(void); + +/* Disable phy resolving list */ +void ble_phy_resolv_list_disable(void); + +/* + * PHY mode values for 1M, 2M and Coded S=8 are the same as corresponding values + * of PHY. This makes conversion between 'phy' and 'phy_mode' easier and it also + * means that default coding for Coded will be S=8, unless explicitly translated + * to S=2. + */ +#define BLE_PHY_MODE_CODED_500KBPS (0) +#define BLE_PHY_MODE_1M (1) +#define BLE_PHY_MODE_2M (2) +#define BLE_PHY_MODE_CODED_125KBPS (3) + +/* The number of different modes */ +#define BLE_PHY_NUM_MODE (4) + +/* PHY numbers (compatible with HCI) */ +#define BLE_PHY_1M (BLE_HCI_LE_PHY_1M) +#define BLE_PHY_2M (BLE_HCI_LE_PHY_2M) +#define BLE_PHY_CODED (BLE_HCI_LE_PHY_CODED) + +/* PHY bitmasks (compatible with HCI) */ +#define BLE_PHY_MASK_1M (BLE_HCI_LE_PHY_1M_PREF_MASK) +#define BLE_PHY_MASK_2M (BLE_HCI_LE_PHY_2M_PREF_MASK) +#define BLE_PHY_MASK_CODED (BLE_HCI_LE_PHY_CODED_PREF_MASK) + +#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)) +uint32_t ble_phy_mode_pdu_start_off(int phy); +void ble_phy_mode_set(uint8_t tx_phy_mode, uint8_t rx_phy_mode); +#else +#define ble_phy_mode_pdu_start_off(phy) (40) + +#endif + +int ble_phy_get_cur_phy(void); +static inline int ble_ll_phy_to_phy_mode(int phy, int phy_options) +{ + int phy_mode; + + /* + * 'phy' value can be used as 'phy_mode' value unless S=2 coding is explicitly + * required. By default we'll use S=2 for Coded. + */ + phy_mode = phy; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + if (phy == BLE_PHY_CODED && phy_options == BLE_HCI_LE_PHY_CODED_S2_PREF) { + phy_mode = BLE_PHY_MODE_CODED_500KBPS; + } +#endif + + return phy_mode; +} + +#if MYNEWT_VAL(BLE_LL_DTM) +void ble_phy_enable_dtm(void); +void ble_phy_disable_dtm(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* H_BLE_PHY_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_phy_trace.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_phy_trace.h new file mode 100644 index 000000000..c0dca7a0f --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_phy_trace.h @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_PHY_TRACE_ +#define H_BLE_PHY_TRACE_ + +#include "nimble/porting/nimble/include/os/os_trace_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BLE_PHY_TRACE_ID_START_TX 0 +#define BLE_PHY_TRACE_ID_START_RX 1 +#define BLE_PHY_TRACE_ID_DISABLE 2 + +#if MYNEWT_VAL(BLE_PHY_SYSVIEW) + +extern uint32_t ble_phy_trace_off; + +void ble_phy_trace_init(void); + +static inline void +ble_phy_trace_void(unsigned id) +{ + os_trace_api_void(ble_phy_trace_off + id); +} + +static inline void +ble_phy_trace_u32(unsigned id, uint32_t p1) +{ + os_trace_api_u32(ble_phy_trace_off + id, p1); +} + +static inline void +ble_phy_trace_u32x2(unsigned id, uint32_t p1, uint32_t p2) +{ + os_trace_api_u32x2(ble_phy_trace_off + id, p1, p2); +} + +static inline void +ble_phy_trace_u32x3(unsigned id, uint32_t p1, uint32_t p2, uint32_t p3) +{ + os_trace_api_u32x3(ble_phy_trace_off + id, p1, p2, p3); +} + +#else + +static inline void +ble_phy_trace_init(void) +{ +} + +static inline void +ble_phy_trace_void(unsigned id) +{ +} + +static inline void +ble_phy_trace_u32(unsigned id, uint32_t p1) +{ +} + +static inline void +ble_phy_trace_u32x2(unsigned id, uint32_t p1, uint32_t p2) +{ +} + +static inline void +ble_phy_trace_u32x3(unsigned id, uint32_t p1, uint32_t p2, uint32_t p3) +{ +} + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* H_BLE_PHY_TRACE_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/pkg.yml new file mode 100644 index 000000000..96c636798 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/pkg.yml @@ -0,0 +1,38 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: nimble/controller +pkg.description: Controller side of the nimble Bluetooth Smart stack. +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - ble + - bluetooth + +pkg.req_apis: + - ble_driver + - ble_transport + - stats + +pkg.deps: + - "@apache-mynewt-core/kernel/os" + - nimble + +pkg.init: + ble_ll_init: 'MYNEWT_VAL(BLE_LL_SYSINIT_STAGE)' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll.c new file mode 100644 index 000000000..6a2ca63b9 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll.c @@ -0,0 +1,1720 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef ESP_PLATFORM + +#include +#include +#include +#include +#include "nimble/porting/nimble/include/sysinit/sysinit.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/porting/nimble/include/os/os_cputime.h" +#include "nimble/porting/nimble/include/stats/stats.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/include/nimble/nimble_opt.h" +#include "nimble/nimble/include/nimble/hci_common.h" +#include "nimble/nimble/include/nimble/ble_hci_trans.h" +#include "../include/controller/ble_hw.h" +#include "../include/controller/ble_phy.h" +#include "../include/controller/ble_phy_trace.h" +#include "../include/controller/ble_ll.h" +#include "../include/controller/ble_ll_adv.h" +#include "../include/controller/ble_ll_sched.h" +#include "../include/controller/ble_ll_scan.h" +#include "../include/controller/ble_ll_hci.h" +#include "../include/controller/ble_ll_whitelist.h" +#include "../include/controller/ble_ll_resolv.h" +#include "../include/controller/ble_ll_rfmgmt.h" +#include "../include/controller/ble_ll_trace.h" +#include "../include/controller/ble_ll_sync.h" +#include "ble_ll_conn_priv.h" + +#if MYNEWT_VAL(BLE_LL_DTM) +#include "ble_ll_dtm_priv.h" +#endif + +/* XXX: + * + * 1) use the sanity task! + * 2) Need to figure out what to do with packets that we hand up that did + * not pass the filter policy for the given state. Currently I count all + * packets I think. Need to figure out what to do with this. + * 3) For the features defined, we need to conditionally compile code. + * 4) Should look into always disabled the wfr interrupt if we receive the + * start of a frame. Need to look at the various states to see if this is the + * right thing to do. + */ + +/* Supported states */ +#define BLE_LL_S_NCA (0x00000000001) +#define BLE_LL_S_SA (0x00000000002) +#define BLE_LL_S_CA (0x00000000004) +#define BLE_LL_S_HDCA (0x00000000008) +#define BLE_LL_S_PS (0x00000000010) +#define BLE_LL_S_AS (0x00000000020) +#define BLE_LL_S_INIT (0x00000000040) +#define BLE_LL_S_SLAVE (0x00000000080) +#define BLE_LL_S_NCA_PS (0x00000000100) +#define BLE_LL_S_SA_PS (0x00000000200) +#define BLE_LL_S_CA_PS (0x00000000400) +#define BLE_LL_S_HDCA_PS (0x00000000800) +#define BLE_LL_S_NCA_AS (0x00000001000) +#define BLE_LL_S_SA_AS (0x00000002000) +#define BLE_LL_S_CA_AS (0x00000004000) +#define BLE_LL_S_HDCA_AS (0x00000008000) +#define BLE_LL_S_NCA_INIT (0x00000010000) +#define BLE_LL_S_SA_INIT (0x00000020000) +#define BLE_LL_S_NCA_MASTER (0x00000040000) +#define BLE_LL_S_SA_MASTER (0x00000080000) +#define BLE_LL_S_NCA_SLAVE (0x00000100000) +#define BLE_LL_S_SA_SLAVE (0x00000200000) +#define BLE_LL_S_PS_INIT (0x00000400000) +#define BLE_LL_S_AS_INIT (0x00000800000) +#define BLE_LL_S_PS_MASTER (0x00001000000) +#define BLE_LL_S_AS_MASTER (0x00002000000) +#define BLE_LL_S_PS_SLAVE (0x00004000000) +#define BLE_LL_S_AS_SLAVE (0x00008000000) +#define BLE_LL_S_INIT_MASTER (0x00010000000) +#define BLE_LL_S_LDCA (0x00020000000) +#define BLE_LL_S_LDCA_PS (0x00040000000) +#define BLE_LL_S_LDCA_AS (0x00080000000) +#define BLE_LL_S_CA_INIT (0x00100000000) +#define BLE_LL_S_HDCA_INIT (0x00200000000) +#define BLE_LL_S_LDCA_INIT (0x00400000000) +#define BLE_LL_S_CA_MASTER (0x00800000000) +#define BLE_LL_S_HDCA_MASTER (0x01000000000) +#define BLE_LL_S_LDCA_MASTER (0x02000000000) +#define BLE_LL_S_CA_SLAVE (0x04000000000) +#define BLE_LL_S_HDCA_SLAVE (0x08000000000) +#define BLE_LL_S_LDCA_SLAVE (0x10000000000) +#define BLE_LL_S_INIT_SLAVE (0x20000000000) + +#define BLE_LL_SUPPORTED_STATES \ +( \ + BLE_LL_S_NCA | \ + BLE_LL_S_SA | \ + BLE_LL_S_CA | \ + BLE_LL_S_HDCA | \ + BLE_LL_S_PS | \ + BLE_LL_S_AS | \ + BLE_LL_S_INIT | \ + BLE_LL_S_SLAVE | \ + BLE_LL_S_NCA_PS | \ + BLE_LL_S_SA_PS | \ + BLE_LL_S_CA_PS | \ + BLE_LL_S_HDCA_PS | \ + BLE_LL_S_NCA_AS | \ + BLE_LL_S_SA_AS | \ + BLE_LL_S_CA_AS | \ + BLE_LL_S_HDCA_AS | \ + BLE_LL_S_NCA_INIT | \ + BLE_LL_S_SA_INIT | \ + BLE_LL_S_NCA_MASTER | \ + BLE_LL_S_SA_MASTER | \ + BLE_LL_S_NCA_SLAVE | \ + BLE_LL_S_SA_SLAVE | \ + BLE_LL_S_PS_INIT | \ + BLE_LL_S_AS_INIT | \ + BLE_LL_S_PS_MASTER | \ + BLE_LL_S_AS_MASTER | \ + BLE_LL_S_PS_SLAVE | \ + BLE_LL_S_AS_SLAVE | \ + BLE_LL_S_INIT_MASTER | \ + BLE_LL_S_LDCA | \ + BLE_LL_S_LDCA_PS | \ + BLE_LL_S_LDCA_AS | \ + BLE_LL_S_CA_INIT | \ + BLE_LL_S_HDCA_INIT | \ + BLE_LL_S_LDCA_INIT | \ + BLE_LL_S_CA_MASTER | \ + BLE_LL_S_HDCA_MASTER | \ + BLE_LL_S_LDCA_MASTER | \ + BLE_LL_S_CA_SLAVE | \ + BLE_LL_S_HDCA_SLAVE | \ + BLE_LL_S_LDCA_SLAVE | \ + BLE_LL_S_INIT_SLAVE) + +/* The global BLE LL data object */ +struct ble_ll_obj g_ble_ll_data; + +/* Global link layer statistics */ +STATS_SECT_DECL(ble_ll_stats) ble_ll_stats; +STATS_NAME_START(ble_ll_stats) + STATS_NAME(ble_ll_stats, hci_cmds) + STATS_NAME(ble_ll_stats, hci_cmd_errs) + STATS_NAME(ble_ll_stats, hci_events_sent) + STATS_NAME(ble_ll_stats, bad_ll_state) + STATS_NAME(ble_ll_stats, bad_acl_hdr) + STATS_NAME(ble_ll_stats, no_bufs) + STATS_NAME(ble_ll_stats, rx_adv_pdu_crc_ok) + STATS_NAME(ble_ll_stats, rx_adv_pdu_crc_err) + STATS_NAME(ble_ll_stats, rx_adv_bytes_crc_ok) + STATS_NAME(ble_ll_stats, rx_adv_bytes_crc_err) + STATS_NAME(ble_ll_stats, rx_data_pdu_crc_ok) + STATS_NAME(ble_ll_stats, rx_data_pdu_crc_err) + STATS_NAME(ble_ll_stats, rx_data_bytes_crc_ok) + STATS_NAME(ble_ll_stats, rx_data_bytes_crc_err) + STATS_NAME(ble_ll_stats, rx_adv_malformed_pkts) + STATS_NAME(ble_ll_stats, rx_adv_ind) + STATS_NAME(ble_ll_stats, rx_adv_direct_ind) + STATS_NAME(ble_ll_stats, rx_adv_nonconn_ind) + STATS_NAME(ble_ll_stats, rx_adv_ext_ind) + STATS_NAME(ble_ll_stats, rx_scan_reqs) + STATS_NAME(ble_ll_stats, rx_scan_rsps) + STATS_NAME(ble_ll_stats, rx_connect_reqs) + STATS_NAME(ble_ll_stats, rx_scan_ind) + STATS_NAME(ble_ll_stats, rx_aux_connect_rsp) + STATS_NAME(ble_ll_stats, adv_txg) + STATS_NAME(ble_ll_stats, adv_late_starts) + STATS_NAME(ble_ll_stats, adv_resched_pdu_fail) + STATS_NAME(ble_ll_stats, adv_drop_event) + STATS_NAME(ble_ll_stats, sched_state_conn_errs) + STATS_NAME(ble_ll_stats, sched_state_adv_errs) + STATS_NAME(ble_ll_stats, scan_starts) + STATS_NAME(ble_ll_stats, scan_stops) + STATS_NAME(ble_ll_stats, scan_req_txf) + STATS_NAME(ble_ll_stats, scan_req_txg) + STATS_NAME(ble_ll_stats, scan_rsp_txg) + STATS_NAME(ble_ll_stats, aux_missed_adv) + STATS_NAME(ble_ll_stats, aux_scheduled) + STATS_NAME(ble_ll_stats, aux_received) + STATS_NAME(ble_ll_stats, aux_fired_for_read) + STATS_NAME(ble_ll_stats, aux_allocated) + STATS_NAME(ble_ll_stats, aux_freed) + STATS_NAME(ble_ll_stats, aux_sched_cb) + STATS_NAME(ble_ll_stats, aux_conn_req_tx) + STATS_NAME(ble_ll_stats, aux_conn_rsp_tx) + STATS_NAME(ble_ll_stats, aux_conn_rsp_err) + STATS_NAME(ble_ll_stats, aux_scan_req_tx) + STATS_NAME(ble_ll_stats, aux_scan_rsp_err) + STATS_NAME(ble_ll_stats, aux_chain_cnt) + STATS_NAME(ble_ll_stats, aux_chain_err) + STATS_NAME(ble_ll_stats, aux_scan_drop) + STATS_NAME(ble_ll_stats, adv_evt_dropped) + STATS_NAME(ble_ll_stats, scan_timer_stopped) + STATS_NAME(ble_ll_stats, scan_timer_restarted) + STATS_NAME(ble_ll_stats, periodic_adv_drop_event) + STATS_NAME(ble_ll_stats, periodic_chain_drop_event) + STATS_NAME(ble_ll_stats, sync_event_failed) + STATS_NAME(ble_ll_stats, sync_received) + STATS_NAME(ble_ll_stats, sync_chain_failed) + STATS_NAME(ble_ll_stats, sync_missed_err) + STATS_NAME(ble_ll_stats, sync_crc_err) + STATS_NAME(ble_ll_stats, sync_rx_buf_err) + STATS_NAME(ble_ll_stats, sync_scheduled) + STATS_NAME(ble_ll_stats, sched_state_sync_errs) + STATS_NAME(ble_ll_stats, sched_invalid_pdu) +STATS_NAME_END(ble_ll_stats) + +static void ble_ll_event_rx_pkt(struct ble_npl_event *ev); +static void ble_ll_event_tx_pkt(struct ble_npl_event *ev); +static void ble_ll_event_dbuf_overflow(struct ble_npl_event *ev); + +#if MYNEWT + +/* The BLE LL task data structure */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +#define BLE_LL_STACK_SIZE (120) +#else +#define BLE_LL_STACK_SIZE (90) +#endif + +struct os_task g_ble_ll_task; + +OS_TASK_STACK_DEFINE(g_ble_ll_stack, BLE_LL_STACK_SIZE); + +#endif /* MYNEWT */ + +/** Our global device address (public) */ +uint8_t g_dev_addr[BLE_DEV_ADDR_LEN]; + +/** Our random address */ +uint8_t g_random_addr[BLE_DEV_ADDR_LEN]; + +/** Our supported features which can be controller by the host */ +uint64_t g_ble_ll_supported_host_features = 0; + +static const uint16_t g_ble_ll_pdu_header_tx_time[BLE_PHY_NUM_MODE] = +{ + [BLE_PHY_MODE_1M] = + (BLE_LL_PREAMBLE_LEN + BLE_LL_ACC_ADDR_LEN + BLE_LL_CRC_LEN + + BLE_LL_PDU_HDR_LEN) << 3, + [BLE_PHY_MODE_2M] = + (BLE_LL_PREAMBLE_LEN * 2 + BLE_LL_ACC_ADDR_LEN + BLE_LL_CRC_LEN + + BLE_LL_PDU_HDR_LEN) << 2, + /* For Coded PHY we have exact TX times provided by specification: + * - Preamble, Access Address, CI, TERM1 (always coded as S=8) + * - PDU, CRC, TERM2 (coded as S=2 or S=8) + * (Vol 6, Part B, 2.2). + */ + [BLE_PHY_MODE_CODED_125KBPS] = + (80 + 256 + 16 + 24 + 8 * (BLE_LL_PDU_HDR_LEN * 8 + 24 + 3)), + [BLE_PHY_MODE_CODED_500KBPS] = + (80 + 256 + 16 + 24 + 2 * (BLE_LL_PDU_HDR_LEN * 8 + 24 + 3)), +}; + +/** + * Counts the number of advertising PDU's received, by type. For advertising + * PDU's that contain a destination address, we still count these packets even + * if they are not for us. + * + * @param pdu_type + */ +static void +ble_ll_count_rx_adv_pdus(uint8_t pdu_type) +{ + /* Count received packet types */ + switch (pdu_type) { + case BLE_ADV_PDU_TYPE_ADV_EXT_IND: + STATS_INC(ble_ll_stats, rx_adv_ext_ind); + break; + case BLE_ADV_PDU_TYPE_ADV_IND: + STATS_INC(ble_ll_stats, rx_adv_ind); + break; + case BLE_ADV_PDU_TYPE_ADV_DIRECT_IND: + STATS_INC(ble_ll_stats, rx_adv_direct_ind); + break; + case BLE_ADV_PDU_TYPE_ADV_NONCONN_IND: + STATS_INC(ble_ll_stats, rx_adv_nonconn_ind); + break; + case BLE_ADV_PDU_TYPE_SCAN_REQ: + STATS_INC(ble_ll_stats, rx_scan_reqs); + break; + case BLE_ADV_PDU_TYPE_SCAN_RSP: + STATS_INC(ble_ll_stats, rx_scan_rsps); + break; + case BLE_ADV_PDU_TYPE_CONNECT_IND: + STATS_INC(ble_ll_stats, rx_connect_reqs); + break; + case BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP: + STATS_INC(ble_ll_stats, rx_aux_connect_rsp); + break; + case BLE_ADV_PDU_TYPE_ADV_SCAN_IND: + STATS_INC(ble_ll_stats, rx_scan_ind); + break; + default: + break; + } +} + +struct os_mbuf * +ble_ll_rxpdu_alloc(uint16_t len) +{ + struct os_mbuf *om_ret; + struct os_mbuf *om_next; + struct os_mbuf *om; + struct os_mbuf_pkthdr *pkthdr; + uint16_t databuf_len; + int rem_len; + + /* + * Make sure that data in mbuf are word-aligned with and without packet + * header. This is essential for proper and quick copying of received PDUs + * into mbufs. + */ + _Static_assert((offsetof(struct os_mbuf, om_data) & 3) == 0, + "Unaligned om_data"); + _Static_assert(((offsetof(struct os_mbuf, om_data) + + sizeof(struct os_mbuf_pkthdr) + + sizeof(struct ble_mbuf_hdr)) & 3) == 0, + "Unaligned data trailing packet header"); + + om_ret = os_msys_get_pkthdr(len, sizeof(struct ble_mbuf_hdr)); + if (!om_ret) { + goto rxpdu_alloc_fail; + } + + /* Set complete PDU length in packet header */ + pkthdr = OS_MBUF_PKTHDR(om_ret); + pkthdr->omp_len = len; + + rem_len = len; + + /* + * Calculate length of data in memory block. We assume length is rounded + * down to word size so PHY can do word-size aligned data copy to mbufs + * (except for last one) and leave remainder unused. + * + * Note that there likely won't be any remainder here since all pools have + * block size aligned to word size anyway. + */ + databuf_len = om_ret->om_omp->omp_databuf_len & ~3; + + /* + * First mbuf can store less data due to packet header. Also we reserve one + * word for leading space to prepend header when necessary (like for data + * PDU before handing over to HCI) + */ + om_ret->om_data += 4; + rem_len -= databuf_len - om_ret->om_pkthdr_len - 4; + + /* Allocate and chain mbufs until there's enough space to store complete PDU */ + om = om_ret; + while (rem_len > 0) { + om_next = os_msys_get(rem_len, 0); + if (!om_next) { + os_mbuf_free_chain(om_ret); + goto rxpdu_alloc_fail; + } + + SLIST_NEXT(om, om_next) = om_next; + om = om_next; + + rem_len -= databuf_len; + } + + return om_ret; + +rxpdu_alloc_fail: + STATS_INC(ble_ll_stats, no_bufs); + return NULL; +} + +int +ble_ll_chk_txrx_octets(uint16_t octets) +{ + int rc; + + if ((octets < BLE_LL_CONN_SUPP_BYTES_MIN) || + (octets > BLE_LL_CONN_SUPP_BYTES_MAX)) { + rc = 0; + } else { + rc = 1; + } + + return rc; +} + +int +ble_ll_chk_txrx_time(uint16_t time) +{ + int rc; + + if ((time < BLE_LL_CONN_SUPP_TIME_MIN) || + (time > BLE_LL_CONN_SUPP_TIME_MAX)) { + rc = 0; + } else { + rc = 1; + } + + return rc; +} + +/** + * Checks to see if the address is a resolvable private address. + * + * NOTE: the addr_type parameter will be 0 if the address is public; + * any other value is random (all non-zero values). + * + * @param addr + * @param addr_type Public (zero) or Random (non-zero) address + * + * @return int + */ +int +ble_ll_is_rpa(const uint8_t *addr, uint8_t addr_type) +{ + int rc; + + if (addr_type && ((addr[5] & 0xc0) == 0x40)) { + rc = 1; + } else { + rc = 0; + } + return rc; +} + +int +ble_ll_addr_is_id(uint8_t *addr, uint8_t addr_type) +{ + return !addr_type || ((addr[5] & 0xc0) == 0xc0); +} + +int +ble_ll_addr_subtype(const uint8_t *addr, uint8_t addr_type) +{ + if (!addr_type) { + return BLE_LL_ADDR_SUBTYPE_IDENTITY; + } + + switch (addr[5] >> 6) { + case 0: + return BLE_LL_ADDR_SUBTYPE_NRPA; /* NRPA */ + case 1: + return BLE_LL_ADDR_SUBTYPE_RPA; /* RPA */ + default: + return BLE_LL_ADDR_SUBTYPE_IDENTITY; /* static random */ + } +} + +int +ble_ll_is_valid_public_addr(const uint8_t *addr) +{ + int i; + + for (i = 0; i < BLE_DEV_ADDR_LEN; ++i) { + if (addr[i]) { + return 1; + } + } + + return 0; +} + +/* Checks to see that the device is a valid random address */ +int +ble_ll_is_valid_random_addr(const uint8_t *addr) +{ + int i; + int rc; + uint16_t sum; + uint8_t addr_type; + + /* Make sure all bits are neither one nor zero */ + sum = 0; + for (i = 0; i < (BLE_DEV_ADDR_LEN -1); ++i) { + sum += addr[i]; + } + sum += addr[5] & 0x3f; + + if ((sum == 0) || (sum == ((5*255) + 0x3f))) { + return 0; + } + + /* Get the upper two bits of the address */ + rc = 1; + addr_type = addr[5] & 0xc0; + if (addr_type == 0xc0) { + /* Static random address. No other checks needed */ + } else if (addr_type == 0x40) { + /* Resolvable */ + sum = addr[3] + addr[4] + (addr[5] & 0x3f); + if ((sum == 0) || (sum == (255 + 255 + 0x3f))) { + rc = 0; + } + } else if (addr_type == 0) { + /* non-resolvable. Cant be equal to public */ + if (!memcmp(g_dev_addr, addr, BLE_DEV_ADDR_LEN)) { + rc = 0; + } + } else { + /* Invalid upper two bits */ + rc = 0; + } + + return rc; +} +int +ble_ll_is_valid_own_addr_type(uint8_t own_addr_type, const uint8_t *random_addr) +{ + int rc; + + switch (own_addr_type) { + case BLE_HCI_ADV_OWN_ADDR_PUBLIC: +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + case BLE_HCI_ADV_OWN_ADDR_PRIV_PUB: +#endif + rc = ble_ll_is_valid_public_addr(g_dev_addr); + break; + case BLE_HCI_ADV_OWN_ADDR_RANDOM: +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + case BLE_HCI_ADV_OWN_ADDR_PRIV_RAND: +#endif + rc = ble_ll_is_valid_random_addr(random_addr); + break; + default: + rc = 0; + break; + } + + return rc; +} + +int +ble_ll_set_public_addr(const uint8_t *addr) +{ + memcpy(g_dev_addr, addr, BLE_DEV_ADDR_LEN); + + return BLE_ERR_SUCCESS; +} + +/** + * Called from the HCI command parser when the set random address command + * is received. + * + * Context: Link Layer task (HCI command parser) + * + * @param addr Pointer to address + * + * @return int 0: success + */ +int +ble_ll_set_random_addr(const uint8_t *cmdbuf, uint8_t len, bool hci_adv_ext) +{ + const struct ble_hci_le_set_rand_addr_cp *cmd = (const void *) cmdbuf; + + if (len < sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* If the Host issues this command when scanning or legacy advertising is + * enabled, the Controller shall return the error code Command Disallowed. + * + * Test specification extends this also to initiating. + */ + + if (g_ble_ll_conn_create_sm || ble_ll_scan_enabled() || + (!hci_adv_ext && ble_ll_adv_enabled())) { + return BLE_ERR_CMD_DISALLOWED; + } + + if (!ble_ll_is_valid_random_addr(cmd->addr)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + memcpy(g_random_addr, cmd->addr, BLE_DEV_ADDR_LEN); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + /* For instance 0 we need same address if legacy advertising might be + * used. If extended advertising is in use than this command doesn't + * affect instance 0. + */ + if (!hci_adv_ext) + ble_ll_adv_set_random_addr(cmd->addr, 0); +#endif + + return BLE_ERR_SUCCESS; +} + +/** + * Checks to see if an address is our device address (either public or + * random) + * + * @param addr + * @param addr_type + * + * @return int 0: not our device address. 1: is our device address + */ +int +ble_ll_is_our_devaddr(uint8_t *addr, int addr_type) +{ + int rc; + uint8_t *our_addr; + + if (addr_type) { + our_addr = g_random_addr; + } else { + our_addr = g_dev_addr; + } + + rc = 0; + if (!memcmp(our_addr, addr, BLE_DEV_ADDR_LEN)) { + rc = 1; + } + + return rc; +} + +/** + * Get identity address + * + * @param addr_type Random (1). Public(0) + * + * @return pointer to identity address of given type. + */ +uint8_t* +ble_ll_get_our_devaddr(uint8_t addr_type) +{ + if (addr_type) { + return g_random_addr; + } + + return g_dev_addr; +} + +/** + * Wait for response timeout function + * + * Context: interrupt (ble scheduler) + * + * @param arg + */ +void +ble_ll_wfr_timer_exp(void *arg) +{ + int rx_start; + uint8_t lls; + + rx_start = ble_phy_rx_started(); + lls = g_ble_ll_data.ll_state; + + ble_ll_trace_u32x3(BLE_LL_TRACE_ID_WFR_EXP, lls, ble_phy_xcvr_state_get(), + (uint32_t)rx_start); + + /* If we have started a reception, there is nothing to do here */ + if (!rx_start) { + switch (lls) { + case BLE_LL_STATE_ADV: + ble_ll_adv_wfr_timer_exp(); + break; + case BLE_LL_STATE_CONNECTION: + ble_ll_conn_wfr_timer_exp(); + break; + case BLE_LL_STATE_SCANNING: + ble_ll_scan_wfr_timer_exp(); + break; + case BLE_LL_STATE_INITIATING: + ble_ll_conn_init_wfr_timer_exp(); + break; +#if MYNEWT_VAL(BLE_LL_DTM) + case BLE_LL_STATE_DTM: + ble_ll_dtm_wfr_timer_exp(); + break; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + case BLE_LL_STATE_SYNC: + ble_ll_sync_wfr_timer_exp(); + break; +#endif + default: + break; + } + } +} + +/** + * ll tx pkt in proc + * + * Process ACL data packet input from host + * + * Context: Link layer task + * + */ +static void +ble_ll_tx_pkt_in(void) +{ + uint16_t handle; + uint16_t length; + uint16_t pb; + struct os_mbuf_pkthdr *pkthdr; + struct os_mbuf *om; + + /* Drain all packets off the queue */ + while (STAILQ_FIRST(&g_ble_ll_data.ll_tx_pkt_q)) { + /* Get mbuf pointer from packet header pointer */ + pkthdr = STAILQ_FIRST(&g_ble_ll_data.ll_tx_pkt_q); + om = (struct os_mbuf *)((uint8_t *)pkthdr - sizeof(struct os_mbuf)); + + /* Remove from queue */ + STAILQ_REMOVE_HEAD(&g_ble_ll_data.ll_tx_pkt_q, omp_next); + + /* Strip HCI ACL header to get handle and length */ + handle = get_le16(om->om_data); + length = get_le16(om->om_data + 2); + os_mbuf_adj(om, sizeof(struct hci_data_hdr)); + + /* Do some basic error checking */ + pb = handle & 0x3000; + if ((pkthdr->omp_len != length) || (pb > 0x1000) || (length == 0)) { + /* This is a bad ACL packet. Count a stat and free it */ + STATS_INC(ble_ll_stats, bad_acl_hdr); + os_mbuf_free_chain(om); + continue; + } + + /* Hand to connection state machine */ + ble_ll_conn_tx_pkt_in(om, handle, length); + } +} + +/** + * Count Link Layer statistics for received PDUs + * + * Context: Link layer task + * + * @param hdr + * @param len + */ +static void +ble_ll_count_rx_stats(struct ble_mbuf_hdr *hdr, uint16_t len, uint8_t pdu_type) +{ + uint8_t crcok; + bool connection_data; + + crcok = BLE_MBUF_HDR_CRC_OK(hdr); + connection_data = (BLE_MBUF_HDR_RX_STATE(hdr) == BLE_LL_STATE_CONNECTION); + +#if MYNEWT_VAL(BLE_LL_DTM) + /* Reuse connection stats for DTM */ + if (!connection_data) { + connection_data = (BLE_MBUF_HDR_RX_STATE(hdr) == BLE_LL_STATE_DTM); + } +#endif + + if (crcok) { + if (connection_data) { + STATS_INC(ble_ll_stats, rx_data_pdu_crc_ok); + STATS_INCN(ble_ll_stats, rx_data_bytes_crc_ok, len); + } else { + STATS_INC(ble_ll_stats, rx_adv_pdu_crc_ok); + STATS_INCN(ble_ll_stats, rx_adv_bytes_crc_ok, len); + ble_ll_count_rx_adv_pdus(pdu_type); + } + } else { + if (connection_data) { + STATS_INC(ble_ll_stats, rx_data_pdu_crc_err); + STATS_INCN(ble_ll_stats, rx_data_bytes_crc_err, len); + } else { + STATS_INC(ble_ll_stats, rx_adv_pdu_crc_err); + STATS_INCN(ble_ll_stats, rx_adv_bytes_crc_err, len); + } + } +} + +/** + * ll rx pkt in + * + * Process received packet from PHY. + * + * Context: Link layer task + * + */ +static void +ble_ll_rx_pkt_in(void) +{ + os_sr_t sr; + uint8_t pdu_type; + uint8_t *rxbuf; + struct os_mbuf_pkthdr *pkthdr; + struct ble_mbuf_hdr *ble_hdr; + struct os_mbuf *m; + + /* Drain all packets off the queue */ + while (STAILQ_FIRST(&g_ble_ll_data.ll_rx_pkt_q)) { + /* Get mbuf pointer from packet header pointer */ + pkthdr = STAILQ_FIRST(&g_ble_ll_data.ll_rx_pkt_q); + m = (struct os_mbuf *)((uint8_t *)pkthdr - sizeof(struct os_mbuf)); + + /* Remove from queue */ + OS_ENTER_CRITICAL(sr); + STAILQ_REMOVE_HEAD(&g_ble_ll_data.ll_rx_pkt_q, omp_next); + OS_EXIT_CRITICAL(sr); + + /* Note: pdu type wont get used unless this is an advertising pdu */ + ble_hdr = BLE_MBUF_HDR_PTR(m); + rxbuf = m->om_data; + pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK; + ble_ll_count_rx_stats(ble_hdr, pkthdr->omp_len, pdu_type); + + /* Process the data or advertising pdu */ + /* Process the PDU */ + switch (BLE_MBUF_HDR_RX_STATE(ble_hdr)) { + case BLE_LL_STATE_CONNECTION: + ble_ll_conn_rx_data_pdu(m, ble_hdr); + /* m is going to be free by function above */ + m = NULL; + break; + case BLE_LL_STATE_ADV: + ble_ll_adv_rx_pkt_in(pdu_type, rxbuf, ble_hdr); + break; + case BLE_LL_STATE_SCANNING: + ble_ll_scan_rx_pkt_in(pdu_type, m, ble_hdr); + break; + case BLE_LL_STATE_INITIATING: + ble_ll_init_rx_pkt_in(pdu_type, rxbuf, ble_hdr); + break; +#if MYNEWT_VAL(BLE_LL_DTM) + case BLE_LL_STATE_DTM: + ble_ll_dtm_rx_pkt_in(m, ble_hdr); + break; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + case BLE_LL_STATE_SYNC: + ble_ll_sync_rx_pkt_in(m, ble_hdr); + break; +#endif + default: + /* Any other state should never occur */ + STATS_INC(ble_ll_stats, bad_ll_state); + break; + } + if (m) { + /* Free the packet buffer */ + os_mbuf_free_chain(m); + } + } +} + +/** + * Called to put a packet on the Link Layer receive packet queue. + * + * @param rxpdu Pointer to received PDU + */ +void +ble_ll_rx_pdu_in(struct os_mbuf *rxpdu) +{ + struct os_mbuf_pkthdr *pkthdr; + + pkthdr = OS_MBUF_PKTHDR(rxpdu); + STAILQ_INSERT_TAIL(&g_ble_ll_data.ll_rx_pkt_q, pkthdr, omp_next); + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_data.ll_rx_pkt_ev); +} + +/** + * Called to put a packet on the Link Layer transmit packet queue. + * + * @param txpdu Pointer to transmit packet + */ +void +ble_ll_acl_data_in(struct os_mbuf *txpkt) +{ + os_sr_t sr; + struct os_mbuf_pkthdr *pkthdr; + + pkthdr = OS_MBUF_PKTHDR(txpkt); + OS_ENTER_CRITICAL(sr); + STAILQ_INSERT_TAIL(&g_ble_ll_data.ll_tx_pkt_q, pkthdr, omp_next); + OS_EXIT_CRITICAL(sr); + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_data.ll_tx_pkt_ev); +} + +/** + * Called to post event to Link Layer when a data buffer overflow has + * occurred. + * + * Context: Interrupt + * + */ +void +ble_ll_data_buffer_overflow(void) +{ + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_data.ll_dbuf_overflow_ev); +} + +/** + * Called when a HW error occurs. + * + * Context: Interrupt + */ +void +ble_ll_hw_error(void) +{ + ble_npl_callout_reset(&g_ble_ll_data.ll_hw_err_timer, 0); +} + +/** + * Called when the HW error timer expires. + * + * @param arg + */ +static void +ble_ll_hw_err_timer_cb(struct ble_npl_event *ev) +{ + if (ble_ll_hci_ev_hw_err(BLE_HW_ERR_HCI_SYNC_LOSS)) { + /* + * Restart callout if failed to allocate event. Try to allocate an + * event every 50 milliseconds (or each OS tick if a tick is longer + * than 100 msecs). + */ + ble_npl_callout_reset(&g_ble_ll_data.ll_hw_err_timer, + ble_npl_time_ms_to_ticks32(50)); + } +} + +/** + * Called upon start of received PDU + * + * Context: Interrupt + * + * @param rxpdu + * chan + * + * @return int + * < 0: A frame we dont want to receive. + * = 0: Continue to receive frame. Dont go from rx to tx + * > 0: Continue to receive frame and go from rx to tx when done + */ +int +ble_ll_rx_start(uint8_t *rxbuf, uint8_t chan, struct ble_mbuf_hdr *rxhdr) +{ + int rc; + uint8_t pdu_type; + + /* Advertising channel PDU */ + pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK; + + ble_ll_trace_u32x2(BLE_LL_TRACE_ID_RX_START, g_ble_ll_data.ll_state, + pdu_type); + + switch (g_ble_ll_data.ll_state) { + case BLE_LL_STATE_CONNECTION: + rc = ble_ll_conn_rx_isr_start(rxhdr, ble_phy_access_addr_get()); + break; + case BLE_LL_STATE_ADV: + rc = ble_ll_adv_rx_isr_start(pdu_type); + break; + case BLE_LL_STATE_INITIATING: + rc = ble_ll_init_rx_isr_start(pdu_type, rxhdr); + break; + case BLE_LL_STATE_SCANNING: + rc = ble_ll_scan_rx_isr_start(pdu_type, &rxhdr->rxinfo.flags); + break; +#if MYNEWT_VAL(BLE_LL_DTM) + case BLE_LL_STATE_DTM: + rc = ble_ll_dtm_rx_isr_start(rxhdr, ble_phy_access_addr_get()); + break; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + case BLE_LL_STATE_SYNC: + rc = ble_ll_sync_rx_isr_start(pdu_type, rxhdr); + break; +#endif + default: + /* Should not be in this state! */ + rc = -1; + STATS_INC(ble_ll_stats, bad_ll_state); + break; + } + + return rc; +} + +/** + * Called by the PHY when a receive packet has ended. + * + * NOTE: Called from interrupt context! + * + * @param rxbuf Pointer to received PDU data + * rxhdr Pointer to BLE header of received mbuf + * + * @return int + * < 0: Disable the phy after reception. + * == 0: Success. Do not disable the PHY. + * > 0: Do not disable PHY as that has already been done. + */ +int +ble_ll_rx_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) +{ + int rc; + int badpkt; + uint8_t pdu_type; + uint8_t len; + uint8_t crcok; + struct os_mbuf *rxpdu; + + /* Get CRC status from BLE header */ + crcok = BLE_MBUF_HDR_CRC_OK(rxhdr); + + /* Get advertising PDU type and length */ + pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK; + len = rxbuf[1]; + + ble_ll_trace_u32x3(BLE_LL_TRACE_ID_RX_END, pdu_type, len, + rxhdr->rxinfo.flags); + +#if MYNEWT_VAL(BLE_LL_DTM) + if (BLE_MBUF_HDR_RX_STATE(rxhdr) == BLE_LL_STATE_DTM) { + rc = ble_ll_dtm_rx_isr_end(rxbuf, rxhdr); + return rc; + } +#endif + + if (BLE_MBUF_HDR_RX_STATE(rxhdr) == BLE_LL_STATE_CONNECTION) { + rc = ble_ll_conn_rx_isr_end(rxbuf, rxhdr); + return rc; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + if (BLE_MBUF_HDR_RX_STATE(rxhdr) == BLE_LL_STATE_SYNC) { + rc = ble_ll_sync_rx_isr_end(rxbuf, rxhdr); + return rc; + } +#endif + + /* If the CRC checks, make sure lengths check! */ + badpkt = 0; + if (crcok) { + switch (pdu_type) { + case BLE_ADV_PDU_TYPE_SCAN_REQ: + case BLE_ADV_PDU_TYPE_ADV_DIRECT_IND: + if (len != BLE_SCAN_REQ_LEN) { + badpkt = 1; + } + break; + case BLE_ADV_PDU_TYPE_SCAN_RSP: + case BLE_ADV_PDU_TYPE_ADV_IND: + case BLE_ADV_PDU_TYPE_ADV_SCAN_IND: + case BLE_ADV_PDU_TYPE_ADV_NONCONN_IND: + if ((len < BLE_DEV_ADDR_LEN) || (len > BLE_ADV_SCAN_IND_MAX_LEN)) { + badpkt = 1; + } + break; + case BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP: + break; + case BLE_ADV_PDU_TYPE_ADV_EXT_IND: + break; + case BLE_ADV_PDU_TYPE_CONNECT_IND: + if (len != BLE_CONNECT_REQ_LEN) { + badpkt = 1; + } + break; + default: + badpkt = 1; + break; + } + + /* If this is a malformed packet, just kill it here */ + if (badpkt) { + STATS_INC(ble_ll_stats, rx_adv_malformed_pkts); + } + } + + /* Hand packet to the appropriate state machine (if crc ok) */ + rxpdu = NULL; + switch (BLE_MBUF_HDR_RX_STATE(rxhdr)) { + case BLE_LL_STATE_ADV: + if (!badpkt) { + rxpdu = ble_ll_rxpdu_alloc(len + BLE_LL_PDU_HDR_LEN); + if (rxpdu) { + ble_phy_rxpdu_copy(rxbuf, rxpdu); + } + } + rc = ble_ll_adv_rx_isr_end(pdu_type, rxpdu, crcok); + break; + case BLE_LL_STATE_SCANNING: + if (!badpkt) { + rxpdu = ble_ll_rxpdu_alloc(len + BLE_LL_PDU_HDR_LEN); + if (rxpdu) { + ble_phy_rxpdu_copy(rxbuf, rxpdu); + } + } + rc = ble_ll_scan_rx_isr_end(rxpdu, crcok); + break; + case BLE_LL_STATE_INITIATING: + rc = ble_ll_init_rx_isr_end(rxbuf, crcok, rxhdr); + break; + default: + rc = -1; + STATS_INC(ble_ll_stats, bad_ll_state); + break; + } + + /* Hand packet up to higher layer (regardless of CRC failure) */ + if (rxpdu) { + ble_ll_rx_pdu_in(rxpdu); + } + + return rc; +} + +uint8_t +ble_ll_tx_mbuf_pducb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) +{ + struct os_mbuf *txpdu; + struct ble_mbuf_hdr *ble_hdr; + + txpdu = pducb_arg; + BLE_LL_ASSERT(txpdu); + ble_hdr = BLE_MBUF_HDR_PTR(txpdu); + + os_mbuf_copydata(txpdu, ble_hdr->txinfo.offset, ble_hdr->txinfo.pyld_len, + dptr); + + *hdr_byte = ble_hdr->txinfo.hdr_byte; + + return ble_hdr->txinfo.pyld_len; +} + +uint8_t +ble_ll_tx_flat_mbuf_pducb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) +{ + struct os_mbuf *txpdu; + struct ble_mbuf_hdr *ble_hdr; + + txpdu = pducb_arg; + BLE_LL_ASSERT(txpdu); + ble_hdr = BLE_MBUF_HDR_PTR(txpdu); + + memcpy(dptr, txpdu->om_data, ble_hdr->txinfo.pyld_len); + + *hdr_byte = ble_hdr->txinfo.hdr_byte; + + return ble_hdr->txinfo.pyld_len; +} + +static void +ble_ll_event_rx_pkt(struct ble_npl_event *ev) +{ + ble_ll_rx_pkt_in(); +} + +static void +ble_ll_event_tx_pkt(struct ble_npl_event *ev) +{ + ble_ll_tx_pkt_in(); +} + +static void +ble_ll_event_dbuf_overflow(struct ble_npl_event *ev) +{ + ble_ll_hci_ev_databuf_overflow(); +} + +static void +ble_ll_event_comp_pkts(struct ble_npl_event *ev) +{ + ble_ll_conn_num_comp_pkts_event_send(NULL); +} + +/** + * Link Layer task. + * + * This is the task that runs the Link Layer. + * + * @param arg + */ +void +ble_ll_task(void *arg) +{ + struct ble_npl_event *ev; + + /* Init ble phy */ + ble_phy_init(); + + /* Set output power to 1mW (0 dBm) */ + ble_phy_txpwr_set(MYNEWT_VAL(BLE_LL_TX_PWR_DBM)); + + /* Register callback for transport */ + ble_hci_trans_cfg_ll(ble_ll_hci_cmd_rx, NULL, ble_ll_hci_acl_rx, NULL); + + /* Tell the host that we are ready to receive packets */ + ble_ll_hci_send_noop(); + + ble_ll_rand_start(); + + while (1) { + ev = ble_npl_eventq_get(&g_ble_ll_data.ll_evq, BLE_NPL_TIME_FOREVER); + assert(ev); + ble_npl_event_run(ev); + } +} + +/** + * ble ll state set + * + * Called to set the current link layer state. + * + * Context: Interrupt and Link Layer task + * + * @param ll_state + */ +void +ble_ll_state_set(uint8_t ll_state) +{ + g_ble_ll_data.ll_state = ll_state; +} + +/** + * ble ll state get + * + * Called to get the current link layer state. + * + * Context: Link Layer task (can be called from interrupt context though). + * + * @return ll_state + */ +uint8_t +ble_ll_state_get(void) +{ + return g_ble_ll_data.ll_state; +} + +/** + * ble ll event send + * + * Send an event to the Link Layer task + * + * @param ev Event to add to the Link Layer event queue. + */ +void +ble_ll_event_send(struct ble_npl_event *ev) +{ + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, ev); +} + +/** + * Returns the features supported by the link layer + * + * @return uint8_t bitmask of supported features. + */ +uint64_t +ble_ll_read_supp_states(void) +{ + return BLE_LL_SUPPORTED_STATES; +} + +/** + * Returns the features supported by the link layer + * + * @return uint64_t bitmask of supported features. + */ +uint64_t +ble_ll_read_supp_features(void) +{ + return g_ble_ll_data.ll_supp_features; +} + +/** + * Sets the features controlled by the host. + * + * @return HCI command status + */ +int +ble_ll_set_host_feat(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_set_host_feat_cp *cmd = (const void *) cmdbuf; + uint64_t mask; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (!SLIST_EMPTY(&g_ble_ll_conn_active_list)) { + return BLE_ERR_CMD_DISALLOWED; + } + + if ((cmd->bit_num > 0x3F) || (cmd->val > 1)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + mask = (uint64_t)1 << (cmd->bit_num); + if (!(mask & BLE_LL_HOST_CONTROLLED_FEATURES)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (!(mask & g_ble_ll_supported_host_features)) { + return BLE_ERR_UNSUPPORTED; + } + + if (cmd->val == 0) { + g_ble_ll_data.ll_supp_features &= ~(mask); + } else { + g_ble_ll_data.ll_supp_features |= mask; + } + + return BLE_ERR_SUCCESS; +} +/** + * Flush a link layer packet queue. + * + * @param pktq + */ +static void +ble_ll_flush_pkt_queue(struct ble_ll_pkt_q *pktq) +{ + struct os_mbuf_pkthdr *pkthdr; + struct os_mbuf *om; + + /* FLush all packets from Link layer queues */ + while (STAILQ_FIRST(pktq)) { + /* Get mbuf pointer from packet header pointer */ + pkthdr = STAILQ_FIRST(pktq); + om = OS_MBUF_PKTHDR_TO_MBUF(pkthdr); + + /* Remove from queue and free the mbuf */ + STAILQ_REMOVE_HEAD(pktq, omp_next); + os_mbuf_free_chain(om); + } +} + +/** + * Called to initialize a mbuf used by the controller + * + * NOTE: this is only used when the mbuf is created by the controller; + * it should not be used for data packets (ACL data packets) that come from + * the host. This routine assumes that the entire pdu length can fit in + * one mbuf contiguously. + * + * @param m + * @param pdulen + * @param hdr + */ +void +ble_ll_mbuf_init(struct os_mbuf *m, uint8_t pdulen, uint8_t hdr) +{ + struct ble_mbuf_hdr *ble_hdr; + + /* Set mbuf length and packet length */ + m->om_len = pdulen; + OS_MBUF_PKTHDR(m)->omp_len = pdulen; + + /* Set BLE transmit header */ + ble_hdr = BLE_MBUF_HDR_PTR(m); + ble_hdr->txinfo.flags = 0; + ble_hdr->txinfo.offset = 0; + ble_hdr->txinfo.pyld_len = pdulen; + ble_hdr->txinfo.hdr_byte = hdr; +} + +/** + * Called to reset the controller. This performs a "software reset" of the link + * layer; it does not perform a HW reset of the controller nor does it reset + * the HCI interface. + * + * Context: Link Layer task (HCI command) + * + * @return int The ble error code to place in the command complete event that + * is returned when this command is issued. + */ +int +ble_ll_reset(void) +{ + int rc; + os_sr_t sr; + + OS_ENTER_CRITICAL(sr); + ble_phy_disable(); + ble_ll_sched_stop(); + ble_ll_scan_reset(); + ble_ll_rfmgmt_reset(); + OS_EXIT_CRITICAL(sr); + + /* Stop any advertising */ + ble_ll_adv_reset(); + +#if MYNEWT_VAL(BLE_LL_DTM) + ble_ll_dtm_reset(); +#endif + + /* Stop sync */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + ble_ll_sync_reset(); +#endif + + /* FLush all packets from Link layer queues */ + ble_ll_flush_pkt_queue(&g_ble_ll_data.ll_tx_pkt_q); + ble_ll_flush_pkt_queue(&g_ble_ll_data.ll_rx_pkt_q); + + /* Reset LL stats */ + STATS_RESET(ble_ll_stats); + + /* Reset any preferred PHYs */ + g_ble_ll_data.ll_pref_tx_phys = 0; + g_ble_ll_data.ll_pref_rx_phys = 0; + + /* Reset connection module */ + ble_ll_conn_module_reset(); + + /* All this does is re-initialize the event masks so call the hci init */ + ble_ll_hci_init(); + + /* Reset scheduler */ + ble_ll_sched_init(); + + /* Set state to standby */ + ble_ll_state_set(BLE_LL_STATE_STANDBY); + + /* Reset our random address */ + memset(g_random_addr, 0, BLE_DEV_ADDR_LEN); + + /* Clear the whitelist */ + ble_ll_whitelist_clear(); + + /* Reset resolving list */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + ble_ll_resolv_list_reset(); +#endif + + /* Re-initialize the PHY */ + rc = ble_phy_init(); + + return rc; +} + +static void +ble_ll_seed_prng(void) +{ + uint32_t seed; + int i; + + /* Seed random number generator with least significant bytes of device + * address. + */ + seed = 0; + for (i = 0; i < 4; ++i) { + seed |= g_dev_addr[i]; + seed <<= 8; + } + srand(seed); +} + +uint32_t +ble_ll_pdu_tx_time_get(uint16_t payload_len, int phy_mode) +{ + uint32_t usecs; + +#if (BLE_LL_BT5_PHY_SUPPORTED) + if (phy_mode == BLE_PHY_MODE_1M) { + /* 8 usecs per byte */ + usecs = payload_len << 3; + } else if (phy_mode == BLE_PHY_MODE_2M) { + /* 4 usecs per byte */ + usecs = payload_len << 2; + } else if (phy_mode == BLE_PHY_MODE_CODED_125KBPS) { + /* S=8 => 8 * 8 = 64 usecs per byte */ + usecs = payload_len << 6; + } else if (phy_mode == BLE_PHY_MODE_CODED_500KBPS) { + /* S=2 => 2 * 8 = 16 usecs per byte */ + usecs = payload_len << 4; + } else { + BLE_LL_ASSERT(0); + } + + usecs += g_ble_ll_pdu_header_tx_time[phy_mode]; +#else + usecs = (((payload_len) + BLE_LL_PDU_HDR_LEN + BLE_LL_ACC_ADDR_LEN + + BLE_LL_PREAMBLE_LEN + BLE_LL_CRC_LEN) << 3); +#endif + + return usecs; +} + +uint16_t +ble_ll_pdu_max_tx_octets_get(uint32_t usecs, int phy_mode) +{ + uint32_t header_tx_time; + uint16_t octets = 0; + + BLE_LL_ASSERT(phy_mode < BLE_PHY_NUM_MODE); + + header_tx_time = g_ble_ll_pdu_header_tx_time[phy_mode]; + + /* + * Current conn max tx time can be too short to even send a packet header + * and this can happen if we changed connection form uncoded to coded phy. + * However, the lower bound for conn max tx time (all of them) depends on + * current phy (uncoded/coded) but it always allows to send at least 27 + * bytes of payload thus we alwyas return at least 27 from here. + * + * Reference: + * Core v5.0, Vol 6, Part B, section 4.5.10 + * see connEffectiveMaxTxTime and connEffectiveMaxRxTime definitions + */ + + if (usecs < header_tx_time) { + return 27; + } + + usecs -= header_tx_time; + + if (phy_mode == BLE_PHY_MODE_1M) { + /* 8 usecs per byte */ + octets = usecs >> 3; + } else if (phy_mode == BLE_PHY_MODE_2M) { + /* 4 usecs per byte */ + octets = usecs >> 2; + } else if (phy_mode == BLE_PHY_MODE_CODED_125KBPS) { + /* S=8 => 8 * 8 = 64 usecs per byte */ + octets = usecs >> 6; + } else if (phy_mode == BLE_PHY_MODE_CODED_500KBPS) { + /* S=2 => 2 * 8 = 16 usecs per byte */ + octets = usecs >> 4; + } else { + BLE_LL_ASSERT(0); + } + + /* see comment at the beginning */ + return max(27, octets); +} + +static inline bool +ble_ll_is_addr_empty(const uint8_t *addr) +{ + return memcmp(addr, BLE_ADDR_ANY, BLE_DEV_ADDR_LEN) == 0; +} + +/** + * Initialize the Link Layer. Should be called only once + * + * @return int + */ +void +ble_ll_init(void) +{ + int rc; + uint64_t features; + ble_addr_t addr; + struct ble_ll_obj *lldata; + + /* Ensure this function only gets called by sysinit. */ + SYSINIT_ASSERT_ACTIVE(); + + ble_ll_trace_init(); + ble_phy_trace_init(); + + /* Set public device address if not already set */ + if (ble_ll_is_addr_empty(g_dev_addr)) { + /* Use sycfg address if configured, otherwise try to read from HW */ + if (!ble_ll_is_addr_empty(MYNEWT_VAL(BLE_PUBLIC_DEV_ADDR))) { + memcpy(g_dev_addr, MYNEWT_VAL(BLE_PUBLIC_DEV_ADDR), BLE_DEV_ADDR_LEN); + } else { + rc = ble_hw_get_public_addr(&addr); + if (!rc) { + memcpy(g_dev_addr, &addr.val[0], BLE_DEV_ADDR_LEN); + } + } + } + + ble_ll_rfmgmt_init(); + + /* Get pointer to global data object */ + lldata = &g_ble_ll_data; + + /* Set acl pkt size and number */ + lldata->ll_num_acl_pkts = MYNEWT_VAL(BLE_ACL_BUF_COUNT); + lldata->ll_acl_pkt_size = MYNEWT_VAL(BLE_ACL_BUF_SIZE); + + /* Initialize eventq */ + ble_npl_eventq_init(&lldata->ll_evq); + + /* Initialize the transmit (from host) and receive (from phy) queues */ + STAILQ_INIT(&lldata->ll_tx_pkt_q); + STAILQ_INIT(&lldata->ll_rx_pkt_q); + + /* Initialize transmit (from host) and receive packet (from phy) event */ + ble_npl_event_init(&lldata->ll_rx_pkt_ev, ble_ll_event_rx_pkt, NULL); + ble_npl_event_init(&lldata->ll_tx_pkt_ev, ble_ll_event_tx_pkt, NULL); + + /* Initialize data buffer overflow event and completed packets */ + ble_npl_event_init(&lldata->ll_dbuf_overflow_ev, ble_ll_event_dbuf_overflow, NULL); + ble_npl_event_init(&lldata->ll_comp_pkt_ev, ble_ll_event_comp_pkts, NULL); + + /* Initialize the HW error timer */ + /* NOT USED WITH RAM HCI + * Commented out to prevent creating an unnecessary timer + ble_npl_callout_init(&g_ble_ll_data.ll_hw_err_timer, + &g_ble_ll_data.ll_evq, + ble_ll_hw_err_timer_cb, + NULL); + */ + + /* Initialize LL HCI */ + ble_ll_hci_init(); + + /* Init the scheduler */ + ble_ll_sched_init(); + + /* Initialize advertiser */ + ble_ll_adv_init(); + + /* Initialize a scanner */ + ble_ll_scan_init(); + + /* Initialize the connection module */ + ble_ll_conn_module_init(); + + /* Set the supported features. NOTE: we always support extended reject. */ + features = BLE_LL_FEAT_EXTENDED_REJ; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) + features |= BLE_LL_FEAT_DATA_LEN_EXT; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CONN_PARAM_REQ) + features |= BLE_LL_FEAT_CONN_PARM_REQ; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_SLAVE_INIT_FEAT_XCHG) + features |= BLE_LL_FEAT_SLAVE_INIT; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + features |= BLE_LL_FEAT_LE_ENCRYPTION; +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + features |= (BLE_LL_FEAT_LL_PRIVACY | BLE_LL_FEAT_EXT_SCAN_FILT); + ble_ll_resolv_init(); +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) + features |= BLE_LL_FEAT_LE_PING; +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + features |= BLE_LL_FEAT_EXT_ADV; +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) + /* CSA2 */ + features |= BLE_LL_FEAT_CSA2; +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) + features |= BLE_LL_FEAT_LE_2M_PHY; +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + features |= BLE_LL_FEAT_LE_CODED_PHY; +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + features |= BLE_LL_FEAT_PERIODIC_ADV; + ble_ll_sync_init(); +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) + features |= BLE_LL_FEAT_SYNC_TRANS_RECV; + features |= BLE_LL_FEAT_SYNC_TRANS_SEND; +#endif + + /* Initialize random number generation */ + ble_ll_rand_init(); + + /* XXX: This really doesn't belong here, as the address probably has not + * been set yet. + */ + ble_ll_seed_prng(); + + lldata->ll_supp_features = features; + + rc = stats_init_and_reg(STATS_HDR(ble_ll_stats), + STATS_SIZE_INIT_PARMS(ble_ll_stats, STATS_SIZE_32), + STATS_NAME_INIT_PARMS(ble_ll_stats), + "ble_ll"); + SYSINIT_PANIC_ASSERT(rc == 0); + +#if MYNEWT_VAL(BLE_LL_DTM) + ble_ll_dtm_init(); +#endif + +#if MYNEWT + /* Initialize the LL task */ + os_task_init(&g_ble_ll_task, "ble_ll", ble_ll_task, NULL, + MYNEWT_VAL(BLE_LL_PRIO), OS_WAIT_FOREVER, g_ble_ll_stack, + BLE_LL_STACK_SIZE); +#else + +/* + * For non-Mynewt OS it is required that OS creates task for LL and run LL + * routine which is wrapped by nimble_port_ll_task_func(). + */ + +#endif +} + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_adv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_adv.c new file mode 100644 index 000000000..83fd2506c --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_adv.c @@ -0,0 +1,5143 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef ESP_PLATFORM + +#include +#include +#include +#include +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/porting/nimble/include/os/os_cputime.h" + +#if defined(ARDUINO_ARCH_NRF5) && defined(NRF51) +#include "nimble/nimble/drivers/nrf51/include/ble/xcvr.h" +#elif defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) +#include "nimble/nimble/drivers/nrf52/include/ble/xcvr.h" +#endif + +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/include/nimble/nimble_opt.h" +#include "nimble/nimble/include/nimble/hci_common.h" +#include "nimble/nimble/include/nimble/ble_hci_trans.h" +#include "../include/controller/ble_phy.h" +#include "../include/controller/ble_hw.h" +#include "../include/controller/ble_ll.h" +#include "../include/controller/ble_ll_hci.h" +#include "../include/controller/ble_ll_adv.h" +#include "../include/controller/ble_ll_sched.h" +#include "../include/controller/ble_ll_scan.h" +#include "../include/controller/ble_ll_whitelist.h" +#include "../include/controller/ble_ll_resolv.h" +#include "../include/controller/ble_ll_trace.h" +#include "../include/controller/ble_ll_utils.h" +#include "../include/controller/ble_ll_rfmgmt.h" +#include "ble_ll_conn_priv.h" + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(array) \ + (sizeof(array) / sizeof((array)[0])) +#endif + +/* XXX: TODO + * 1) Need to look at advertising and scan request PDUs. Do I allocate these + * once? Do I use a different pool for smaller ones? Do I statically declare + * them? + * 3) How do features get supported? What happens if device does not support + * advertising? (for example) + * 4) How to determine the advertising interval we will actually use. As of + * now, we set it to max. + */ + +/* Scheduling data for secondary channel */ +struct ble_ll_adv_aux { + struct ble_ll_sched_item sch; + uint32_t start_time; + uint16_t aux_data_offset; + uint8_t chan; + uint8_t ext_hdr; + uint8_t aux_data_len; + uint8_t payload_len; +}; + +/* Scheduling data for sync PDUs */ +struct ble_ll_adv_sync { + struct ble_ll_sched_item sch; + uint32_t start_time; + uint16_t sync_data_offset; + uint8_t chan; + uint8_t ext_hdr; + uint8_t sync_data_len; + uint8_t payload_len; +}; + +/* + * Advertising state machine + * + * The advertising state machine data structure. + * + * adv_pdu_len + * The length of the advertising PDU that will be sent. This does not + * include the preamble, access address and CRC. + * + * initiator_addr: + * This is the address that we send in directed advertisements (the + * INITA field). If we are using Privacy this is a RPA that we need to + * generate. We reserve space in the advsm to save time when creating + * the ADV_DIRECT_IND. If own address type is not 2 or 3, this is simply + * the peer address from the set advertising parameters. + */ +struct ble_ll_adv_sm +{ + uint8_t adv_enabled; + uint8_t adv_instance; + uint8_t adv_chanmask; + uint8_t adv_filter_policy; + uint8_t own_addr_type; + uint8_t peer_addr_type; + uint8_t adv_chan; + uint8_t adv_pdu_len; + int8_t adv_rpa_index; + int8_t adv_txpwr; + uint16_t flags; + uint16_t props; + uint16_t adv_itvl_min; + uint16_t adv_itvl_max; + uint32_t adv_itvl_usecs; + uint32_t adv_event_start_time; + uint32_t adv_pdu_start_time; + uint32_t adv_end_time; + uint32_t adv_rpa_timer; + uint8_t adva[BLE_DEV_ADDR_LEN]; + uint8_t adv_rpa[BLE_DEV_ADDR_LEN]; + uint8_t peer_addr[BLE_DEV_ADDR_LEN]; + uint8_t initiator_addr[BLE_DEV_ADDR_LEN]; + struct os_mbuf *adv_data; + struct os_mbuf *new_adv_data; + struct os_mbuf *scan_rsp_data; + struct os_mbuf *new_scan_rsp_data; + uint8_t *conn_comp_ev; + struct ble_npl_event adv_txdone_ev; + struct ble_ll_sched_item adv_sch; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) + uint16_t channel_id; + uint16_t event_cntr; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + uint8_t aux_active : 1; + uint8_t aux_index : 1; + uint8_t aux_first_pdu : 1; + uint8_t aux_not_scanned : 1; + struct ble_mbuf_hdr *rx_ble_hdr; + struct os_mbuf **aux_data; + struct ble_ll_adv_aux aux[2]; + struct ble_npl_event adv_sec_txdone_ev; + uint16_t duration; + uint16_t adi; + uint8_t adv_random_addr[BLE_DEV_ADDR_LEN]; + uint8_t events_max; + uint8_t events; + uint8_t pri_phy; + uint8_t sec_phy; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + struct os_mbuf *periodic_adv_data; + struct os_mbuf *periodic_new_data; + uint32_t periodic_crcinit; /* only 3 bytes are used */ + uint32_t periodic_access_addr; + uint16_t periodic_adv_itvl_min; + uint16_t periodic_adv_itvl_max; + uint16_t periodic_adv_props; + uint16_t periodic_channel_id; + uint16_t periodic_event_cntr; + uint16_t periodic_chain_event_cntr; + uint8_t periodic_adv_enabled : 1; + uint8_t periodic_adv_active : 1; + uint8_t periodic_sync_active : 1; + uint8_t periodic_sync_index : 1; + uint8_t periodic_num_used_chans; + uint8_t periodic_chanmap[BLE_LL_CONN_CHMAP_LEN]; + uint32_t periodic_adv_itvl_ticks; + uint8_t periodic_adv_itvl_rem_usec; + uint8_t periodic_adv_event_start_time_remainder; + uint32_t periodic_adv_event_start_time; + struct ble_ll_adv_sync periodic_sync[2]; + struct ble_npl_event adv_periodic_txdone_ev; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) + uint16_t periodic_event_cntr_last_sent; +#endif +#endif +#endif +}; + +#define BLE_LL_ADV_SM_FLAG_TX_ADD 0x0001 +#define BLE_LL_ADV_SM_FLAG_RX_ADD 0x0002 +#define BLE_LL_ADV_SM_FLAG_SCAN_REQ_NOTIF 0x0004 +#define BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD 0x0008 +#define BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK 0x0030 /* use helpers! */ +#define BLE_LL_ADV_SM_FLAG_ADV_DATA_INCOMPLETE 0x0040 +#define BLE_LL_ADV_SM_FLAG_CONFIGURED 0x0080 +#define BLE_LL_ADV_SM_FLAG_ADV_RPA_TMO 0x0100 +#define BLE_LL_ADV_SM_FLAG_NEW_ADV_DATA 0x0200 +#define BLE_LL_ADV_SM_FLAG_NEW_SCAN_RSP_DATA 0x0400 +#define BLE_LL_ADV_SM_FLAG_PERIODIC_CONFIGURED 0x0800 +#define BLE_LL_ADV_SM_FLAG_PERIODIC_DATA_INCOMPLETE 0x1000 +#define BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING 0x2000 +#define BLE_LL_ADV_SM_FLAG_PERIODIC_NEW_DATA 0x4000 + +#define ADV_DATA_LEN(_advsm) \ + ((_advsm->adv_data) ? OS_MBUF_PKTLEN(advsm->adv_data) : 0) +#define SCAN_RSP_DATA_LEN(_advsm) \ + ((_advsm->scan_rsp_data) ? OS_MBUF_PKTLEN(advsm->scan_rsp_data) : 0) +#define AUX_DATA_LEN(_advsm) \ + (*(_advsm->aux_data) ? OS_MBUF_PKTLEN(*advsm->aux_data) : 0) + +#define AUX_CURRENT(_advsm) (&(_advsm->aux[_advsm->aux_index])) +#define AUX_NEXT(_advsm) (&(_advsm->aux[_advsm->aux_index ^ 1])) + +#define SYNC_CURRENT(_advsm) (&(_advsm->periodic_sync[_advsm->periodic_sync_index])) +#define SYNC_NEXT(_advsm) (&(_advsm->periodic_sync[_advsm->periodic_sync_index ^ 1])) +#define SYNC_DATA_LEN(_advsm) \ + (_advsm->periodic_adv_data ? OS_MBUF_PKTLEN(advsm->periodic_adv_data) : 0) + +/* The advertising state machine global object */ +struct ble_ll_adv_sm g_ble_ll_adv_sm[BLE_ADV_INSTANCES]; +struct ble_ll_adv_sm *g_ble_ll_cur_adv_sm; + +static struct ble_ll_adv_sm * +ble_ll_adv_sm_find_configured(uint8_t instance) +{ + struct ble_ll_adv_sm *advsm; + int i; + + /* in legacy mode we only allow instance 0 */ + if (!ble_ll_hci_adv_mode_ext()) { + BLE_LL_ASSERT(instance == 0); + return &g_ble_ll_adv_sm[0]; + } + + for (i = 0; i < ARRAY_SIZE(g_ble_ll_adv_sm); i++) { + advsm = &g_ble_ll_adv_sm[i]; + + if ((advsm->flags & BLE_LL_ADV_SM_FLAG_CONFIGURED) && + (advsm->adv_instance == instance)) { + return advsm; + } + } + + return NULL; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +static int +ble_ll_adv_active_chanset_is_pri(struct ble_ll_adv_sm *advsm) +{ + return (advsm->flags & BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK) == 0x10; +} + +static int +ble_ll_adv_active_chanset_is_sec(struct ble_ll_adv_sm *advsm) +{ + return (advsm->flags & BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK) == 0x20; +} +#endif + +static void +ble_ll_adv_active_chanset_clear(struct ble_ll_adv_sm *advsm) +{ + os_sr_t sr; + + OS_ENTER_CRITICAL(sr); + advsm->flags &= ~BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK; + OS_EXIT_CRITICAL(sr); +} + +static void +ble_ll_adv_active_chanset_set_pri(struct ble_ll_adv_sm *advsm) +{ + os_sr_t sr; + + OS_ENTER_CRITICAL(sr); + assert((advsm->flags & BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK) == 0); + advsm->flags &= ~BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK; + advsm->flags |= 0x10; + OS_EXIT_CRITICAL(sr); +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +static void +ble_ll_adv_active_chanset_set_sec(struct ble_ll_adv_sm *advsm) +{ + os_sr_t sr; + + OS_ENTER_CRITICAL(sr); + assert((advsm->flags & BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK) == 0); + advsm->flags &= ~BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK; + advsm->flags |= 0x20; + OS_EXIT_CRITICAL(sr); +} +#endif + +static void +ble_ll_adv_flags_set(struct ble_ll_adv_sm *advsm, uint16_t flags) +{ + os_sr_t sr; + + OS_ENTER_CRITICAL(sr); + advsm->flags |= flags; + OS_EXIT_CRITICAL(sr); +} + +static void +ble_ll_adv_flags_clear(struct ble_ll_adv_sm *advsm, uint16_t flags) +{ + os_sr_t sr; + + OS_ENTER_CRITICAL(sr); + advsm->flags &= ~flags; + OS_EXIT_CRITICAL(sr); +} + +static void ble_ll_adv_make_done(struct ble_ll_adv_sm *advsm, struct ble_mbuf_hdr *hdr); +static void ble_ll_adv_sm_init(struct ble_ll_adv_sm *advsm); +static void ble_ll_adv_sm_stop_timeout(struct ble_ll_adv_sm *advsm); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) +static void +ble_ll_adv_rpa_update(struct ble_ll_adv_sm *advsm) +{ + if (ble_ll_resolv_gen_rpa(advsm->peer_addr, advsm->peer_addr_type, + advsm->adva, 1)) { + ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_TX_ADD); + } else { + if (advsm->own_addr_type & 1) { + ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_TX_ADD); + } else { + ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_TX_ADD); + } + } + + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { + if (ble_ll_resolv_gen_rpa(advsm->peer_addr, advsm->peer_addr_type, + advsm->initiator_addr, 0)) { + ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_RX_ADD); + } else { + if (advsm->peer_addr_type & 1) { + ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_RX_ADD); + } else { + ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_RX_ADD); + } + } + } +} + +/** + * Called to change advertisers ADVA and INITA (for directed advertisements) + * as an advertiser needs to adhere to the resolvable private address generation + * timer. + * + * NOTE: the resolvable private address code uses its own timer to regenerate + * local resolvable private addresses. The advertising code uses its own + * timer to reset the INITA (for directed advertisements). This code also sets + * the appropriate txadd and rxadd bits that will go into the advertisement. + * + * Another thing to note: it is possible that an IRK is all zeroes in the + * resolving list. That is why we need to check if the generated address is + * in fact a RPA as a resolving list entry with all zeroes will use the + * identity address (which may be a private address or public). + * + * @param advsm + */ +void +ble_ll_adv_chk_rpa_timeout(struct ble_ll_adv_sm *advsm) +{ + if (advsm->own_addr_type < BLE_HCI_ADV_OWN_ADDR_PRIV_PUB) { + return; + } + + if (advsm->flags & BLE_LL_ADV_SM_FLAG_ADV_RPA_TMO) { + ble_ll_adv_rpa_update(advsm); + ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_ADV_RPA_TMO); + } +} + +void +ble_ll_adv_rpa_timeout(void) +{ + struct ble_ll_adv_sm *advsm; + int i; + + for (i = 0; i < BLE_ADV_INSTANCES; i++) { + advsm = &g_ble_ll_adv_sm[i]; + + if (advsm->adv_enabled && + advsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) { + /* Mark RPA as timed out so we get a new RPA */ + ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_ADV_RPA_TMO); + } + } +} +#endif + +/** + * Calculate the first channel that we should advertise upon when we start + * an advertising event. + * + * @param advsm + * + * @return uint8_t The number of the first channel usable for advertising. + */ +static uint8_t +ble_ll_adv_first_chan(struct ble_ll_adv_sm *advsm) +{ + uint8_t adv_chan; + + /* Set first advertising channel */ + if (advsm->adv_chanmask & 0x01) { + adv_chan = BLE_PHY_ADV_CHAN_START; + } else if (advsm->adv_chanmask & 0x02) { + adv_chan = BLE_PHY_ADV_CHAN_START + 1; + } else { + adv_chan = BLE_PHY_ADV_CHAN_START + 2; + } + + return adv_chan; +} + +/** + * Calculate the final channel that we should advertise upon when we start + * an advertising event. + * + * @param advsm + * + * @return uint8_t The number of the final channel usable for advertising. + */ +static uint8_t +ble_ll_adv_final_chan(struct ble_ll_adv_sm *advsm) +{ + uint8_t adv_chan; + + if (advsm->adv_chanmask & 0x04) { + adv_chan = BLE_PHY_ADV_CHAN_START + 2; + } else if (advsm->adv_chanmask & 0x02) { + adv_chan = BLE_PHY_ADV_CHAN_START + 1; + } else { + adv_chan = BLE_PHY_ADV_CHAN_START; + } + + return adv_chan; +} + +/** + * Create the advertising legacy PDU + * + * @param advsm Pointer to advertisement state machine + */ +static uint8_t +ble_ll_adv_legacy_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) +{ + struct ble_ll_adv_sm *advsm; + uint8_t adv_data_len; + uint8_t pdulen; + uint8_t pdu_type; + + advsm = pducb_arg; + + /* assume this is not a direct ind */ + adv_data_len = ADV_DATA_LEN(advsm); + pdulen = BLE_DEV_ADDR_LEN + adv_data_len; + + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { + pdu_type = BLE_ADV_PDU_TYPE_ADV_DIRECT_IND; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) + pdu_type |= BLE_ADV_PDU_HDR_CHSEL; +#endif + + if (advsm->flags & BLE_LL_ADV_SM_FLAG_RX_ADD) { + pdu_type |= BLE_ADV_PDU_HDR_RXADD_RAND; + } + + adv_data_len = 0; + pdulen = BLE_ADV_DIRECT_IND_LEN; + } else if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { + pdu_type = BLE_ADV_PDU_TYPE_ADV_IND; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) + pdu_type |= BLE_ADV_PDU_HDR_CHSEL; +#endif + } else if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) { + pdu_type = BLE_ADV_PDU_TYPE_ADV_SCAN_IND; + } else { + pdu_type = BLE_ADV_PDU_TYPE_ADV_NONCONN_IND; + } + + /* An invalid advertising data length indicates a memory overwrite */ + assert(adv_data_len <= BLE_ADV_LEGACY_DATA_MAX_LEN); + + /* Set the PDU length in the state machine (includes header) */ + advsm->adv_pdu_len = pdulen + BLE_LL_PDU_HDR_LEN; + + /* Set TxAdd to random if needed. */ + if (advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) { + pdu_type |= BLE_ADV_PDU_HDR_TXADD_RAND; + } + + *hdr_byte = pdu_type; + + /* Construct advertisement */ + memcpy(dptr, advsm->adva, BLE_DEV_ADDR_LEN); + dptr += BLE_DEV_ADDR_LEN; + + /* For ADV_DIRECT_IND add inita */ + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { + memcpy(dptr, advsm->initiator_addr, BLE_DEV_ADDR_LEN); + } + + /* Copy in advertising data, if any */ + if (adv_data_len != 0) { + os_mbuf_copydata(advsm->adv_data, 0, adv_data_len, dptr); + } + + return pdulen; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +static void +ble_ll_adv_put_aux_ptr(uint8_t chan, uint8_t phy, uint32_t offset, + uint8_t *dptr) +{ + dptr[0] = chan; + + if (offset > 245700) { + dptr[0] |= 0x80; + offset = offset / 300; + } else { + offset = offset / 30; + } + + if (offset > 0x1fff) { + offset = 0; + } + + /* offset is 13bits and PHY 3 bits */ + dptr[1] = (offset & 0x000000ff); + dptr[2] = ((offset >> 8) & 0x0000001f) | (phy - 1) << 5; +} + +/** + * Create the advertising PDU + */ +static uint8_t +ble_ll_adv_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) +{ + struct ble_ll_adv_sm *advsm; + uint8_t pdu_type; + uint8_t adv_mode; + uint8_t ext_hdr_len; + uint8_t ext_hdr_flags; + uint32_t offset; + + advsm = pducb_arg; + + assert(ble_ll_adv_active_chanset_is_pri(advsm)); + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + return ble_ll_adv_legacy_pdu_make(dptr, advsm, hdr_byte); + } + + /* only ADV_EXT_IND goes on primary advertising channels */ + pdu_type = BLE_ADV_PDU_TYPE_ADV_EXT_IND; + + /* Set TxAdd to random if needed. */ + if (advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) { + pdu_type |= BLE_ADV_PDU_HDR_TXADD_RAND; + } + + *hdr_byte = pdu_type; + + adv_mode = 0; + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { + adv_mode |= BLE_LL_EXT_ADV_MODE_CONN; + } + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) { + adv_mode |= BLE_LL_EXT_ADV_MODE_SCAN; + } + + ext_hdr_len = BLE_LL_EXT_ADV_FLAGS_SIZE + BLE_LL_EXT_ADV_DATA_INFO_SIZE + + BLE_LL_EXT_ADV_AUX_PTR_SIZE; + ext_hdr_flags = (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT) | + (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT); + + /* ext hdr len and adv mode */ + dptr[0] = ext_hdr_len | (adv_mode << 6); + dptr += 1; + + /* ext hdr flags */ + dptr[0] = ext_hdr_flags; + dptr += 1; + + /* ADI */ + dptr[0] = advsm->adi & 0x00ff; + dptr[1] = advsm->adi >> 8; + dptr += BLE_LL_EXT_ADV_DATA_INFO_SIZE; + + /* AuxPtr */ + if (AUX_CURRENT(advsm)->sch.enqueued) { + offset = os_cputime_ticks_to_usecs(AUX_CURRENT(advsm)->start_time - advsm->adv_pdu_start_time); + } else { + offset = 0; + } + /* Always use channel from 1st AUX */ + ble_ll_adv_put_aux_ptr(AUX_CURRENT(advsm)->chan, advsm->sec_phy, + offset, dptr); + + return BLE_LL_EXT_ADV_HDR_LEN + ext_hdr_len; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) +static void +ble_ll_adv_put_syncinfo(struct ble_ll_adv_sm *advsm, + struct ble_ll_conn_sm *connsm, uint8_t *conn_event_cnt, + uint8_t *dptr) +{ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) + uint8_t anchor_usecs; + uint16_t conn_cnt; +#endif + unsigned int event_cnt_off = 0; + uint32_t offset = 0; + uint32_t anchor; + uint8_t units; + + if (connsm) { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) + anchor = connsm->anchor_point; + anchor_usecs = connsm->anchor_point_usecs; + conn_cnt = connsm->event_cntr; + + /* get anchor for conn event that is before periodic_adv_event_start_time */ + while (CPUTIME_GT(anchor, advsm->periodic_adv_event_start_time)) { + ble_ll_conn_get_anchor(connsm, --conn_cnt, &anchor, &anchor_usecs); + } + + offset = os_cputime_ticks_to_usecs(advsm->periodic_adv_event_start_time - anchor); + offset -= anchor_usecs; + offset += advsm->periodic_adv_event_start_time_remainder; + + /* connEventCount */ + put_le16(conn_event_cnt, conn_cnt); +#endif + } else { + anchor = advsm->periodic_adv_event_start_time; + + /* Get periodic event that is past AUX start time (so that we always + * provide valid offset if it is not too far in future). This can + * happen if advertising event is interleaved with periodic advertising + * event (when chaining). + */ + while (CPUTIME_GT(AUX_CURRENT(advsm)->start_time, anchor)) { + anchor += advsm->periodic_adv_itvl_ticks; + event_cnt_off++; + } + + offset = os_cputime_ticks_to_usecs(anchor - AUX_CURRENT(advsm)->start_time); + offset += advsm->periodic_adv_event_start_time_remainder; + offset += advsm->periodic_adv_itvl_rem_usec; + } + + /* Sync Packet Offset (13 bits), Offset Units (1 bit), Offset Adjust (1 bit), + * RFU (1 bit) + */ + if (offset > 245700) { + units = 0x20; + offset = offset / 300; + + if (offset >= 0x2000) { + if (connsm) { + offset -= 0x2000; + units |= 0x40; + } else { + /* not able to represent time in offset */ + offset = 0; + units = 0x00; + event_cnt_off = 0; + } + } + + } else { + units = 0x00; + offset = offset / 30; + } + + dptr[0] = (offset & 0x000000ff); + dptr[1] = ((offset >> 8) & 0x0000001f) | units; + + /* Interval (2 bytes) */ + put_le16(&dptr[2], advsm->periodic_adv_itvl_max); + + /* Channels Mask (37 bits) */ + dptr[4] = advsm->periodic_chanmap[0]; + dptr[5] = advsm->periodic_chanmap[1]; + dptr[6] = advsm->periodic_chanmap[2]; + dptr[7] = advsm->periodic_chanmap[3]; + dptr[8] = advsm->periodic_chanmap[4] & 0x1f; + + /* SCA (3 bits) */ + dptr[8] |= MYNEWT_VAL(BLE_LL_MASTER_SCA) << 5; + + /* AA (4 bytes) */ + put_le32(&dptr[9], advsm->periodic_access_addr); + + /* CRCInit (3 bytes) */ + dptr[13] = (uint8_t)advsm->periodic_crcinit; + dptr[14] = (uint8_t)(advsm->periodic_crcinit >> 8); + dptr[15] = (uint8_t)(advsm->periodic_crcinit >> 16); + + /* Event Counter (2 bytes) */ + put_le16(&dptr[16], advsm->periodic_event_cntr + event_cnt_off); +} +#endif + +/** + * Create the AUX PDU + */ +static uint8_t +ble_ll_adv_aux_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) +{ + struct ble_ll_adv_sm *advsm; + struct ble_ll_adv_aux *aux; + uint8_t adv_mode; + uint8_t pdu_type; + uint8_t ext_hdr_len; + uint32_t offset; + + advsm = pducb_arg; + aux = AUX_CURRENT(advsm); + + assert(!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)); + assert(ble_ll_adv_active_chanset_is_sec(advsm)); + + /* It's the same for AUX_ADV_IND and AUX_CHAIN_IND */ + pdu_type = BLE_ADV_PDU_TYPE_AUX_ADV_IND; + + /* We do not create scannable PDUs here - this is handled separately */ + adv_mode = 0; + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { + adv_mode |= BLE_LL_EXT_ADV_MODE_CONN; + } + + ext_hdr_len = aux->payload_len - BLE_LL_EXT_ADV_HDR_LEN - aux->aux_data_len; + dptr[0] = (adv_mode << 6) | ext_hdr_len; + dptr += 1; + + /* only put flags if needed */ + if (aux->ext_hdr) { + dptr[0] = aux->ext_hdr; + dptr += 1; + } + + if (aux->ext_hdr & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) { + + /* Set TxAdd to random if needed. */ + if (advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) { + pdu_type |= BLE_ADV_PDU_HDR_TXADD_RAND; + } + + memcpy(dptr, advsm->adva, BLE_LL_EXT_ADV_ADVA_SIZE); + dptr += BLE_LL_EXT_ADV_ADVA_SIZE; + } + + if (aux->ext_hdr & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) { + memcpy(dptr, advsm->initiator_addr, BLE_LL_EXT_ADV_TARGETA_SIZE); + dptr += BLE_LL_EXT_ADV_TARGETA_SIZE; + + /* Set RxAdd to random if needed. */ + if (advsm->flags & BLE_LL_ADV_SM_FLAG_RX_ADD) { + pdu_type |= BLE_ADV_PDU_HDR_RXADD_RAND; + } + } + + if (aux->ext_hdr & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) { + dptr[0] = advsm->adi & 0x00ff; + dptr[1] = advsm->adi >> 8; + dptr += BLE_LL_EXT_ADV_DATA_INFO_SIZE; + } + + if (aux->ext_hdr & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) { + if (!AUX_NEXT(advsm)->sch.enqueued) { + /* + * Trim data here in case we do not have next aux scheduled. This + * can happen if next aux was outside advertising set period and + * was removed from scheduler. + */ + offset = 0; + } else if (advsm->rx_ble_hdr) { + offset = os_cputime_ticks_to_usecs(AUX_NEXT(advsm)->start_time - advsm->rx_ble_hdr->beg_cputime); + offset -= (advsm->rx_ble_hdr->rem_usecs + ble_ll_pdu_tx_time_get(12, advsm->sec_phy) + BLE_LL_IFS); + } else { + offset = os_cputime_ticks_to_usecs(AUX_NEXT(advsm)->start_time - aux->start_time); + } + + ble_ll_adv_put_aux_ptr(AUX_NEXT(advsm)->chan, advsm->sec_phy, + offset, dptr); + + dptr += BLE_LL_EXT_ADV_AUX_PTR_SIZE; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + if (aux->ext_hdr & (1 << BLE_LL_EXT_ADV_SYNC_INFO_BIT)) { + ble_ll_adv_put_syncinfo(advsm, NULL, NULL, dptr); + dptr += BLE_LL_EXT_ADV_SYNC_INFO_SIZE; + } +#endif + + if (aux->ext_hdr & (1 << BLE_LL_EXT_ADV_TX_POWER_BIT)) { + dptr[0] = advsm->adv_txpwr + ble_ll_get_tx_pwr_compensation(); + dptr += BLE_LL_EXT_ADV_TX_POWER_SIZE; + } + + if (aux->aux_data_len) { + os_mbuf_copydata(*advsm->aux_data, aux->aux_data_offset, + aux->aux_data_len, dptr); + } + + *hdr_byte = pdu_type; + + return aux->payload_len; +} + +static uint8_t +ble_ll_adv_aux_scannable_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) +{ + struct ble_ll_adv_sm *advsm; + uint8_t pdu_type; + uint8_t *ext_hdr_len; + uint8_t *ext_hdr; + uint8_t pdulen; + + advsm = pducb_arg; + + assert(!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)); + assert(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE); + assert(advsm->aux_first_pdu); + assert(ble_ll_adv_active_chanset_is_sec(advsm)); + + pdu_type = BLE_ADV_PDU_TYPE_AUX_ADV_IND; + + ext_hdr_len = &dptr[0]; + ext_hdr = &dptr[1]; + dptr += 2; + + /* Flags always */ + *ext_hdr_len = BLE_LL_EXT_ADV_FLAGS_SIZE; + *ext_hdr = 0; + + /* AdvA when non anonymous */ + if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV)) { + /* Set TxAdd to random if needed. */ + if (advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) { + pdu_type |= BLE_ADV_PDU_HDR_TXADD_RAND; + } + + *ext_hdr_len += BLE_LL_EXT_ADV_ADVA_SIZE; + *ext_hdr |= (1 << BLE_LL_EXT_ADV_ADVA_BIT); + memcpy(dptr, advsm->adva, BLE_LL_EXT_ADV_ADVA_SIZE); + dptr += BLE_LL_EXT_ADV_ADVA_SIZE; + } + + /* TargetA only for directed */ + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { + *ext_hdr_len += BLE_LL_EXT_ADV_TARGETA_SIZE; + *ext_hdr |= (1 << BLE_LL_EXT_ADV_TARGETA_BIT); + memcpy(dptr, advsm->initiator_addr, BLE_LL_EXT_ADV_TARGETA_SIZE); + dptr += BLE_LL_EXT_ADV_TARGETA_SIZE; + + /* Set RxAdd to random if needed. */ + if (advsm->flags & BLE_LL_ADV_SM_FLAG_RX_ADD) { + pdu_type |= BLE_ADV_PDU_HDR_RXADD_RAND; + } + } + + /* ADI always */ + *ext_hdr_len += BLE_LL_EXT_ADV_DATA_INFO_SIZE; + *ext_hdr |= (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT); + dptr[0] = advsm->adi & 0x00ff; + dptr[1] = advsm->adi >> 8; + dptr += BLE_LL_EXT_ADV_DATA_INFO_SIZE; + + /* TxPower if configured */ + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR) { + *ext_hdr_len += BLE_LL_EXT_ADV_TX_POWER_SIZE; + *ext_hdr |= (1 << BLE_LL_EXT_ADV_TX_POWER_BIT); + dptr[0] = advsm->adv_txpwr + ble_ll_get_tx_pwr_compensation(); + dptr += BLE_LL_EXT_ADV_TX_POWER_SIZE; + } + + pdulen = BLE_LL_EXT_ADV_HDR_LEN + *ext_hdr_len; + + *hdr_byte = pdu_type; + *ext_hdr_len |= (BLE_LL_EXT_ADV_MODE_SCAN << 6); + + return pdulen; +} +#endif + +static uint8_t +ble_ll_adv_scan_rsp_legacy_pdu_make(uint8_t *dptr, void *pducb_arg, + uint8_t *hdr_byte) +{ + struct ble_ll_adv_sm *advsm; + uint8_t scan_rsp_len; + uint8_t pdulen; + uint8_t hdr; + + advsm = pducb_arg; + + /* Make sure that the length is valid */ + scan_rsp_len = SCAN_RSP_DATA_LEN(advsm); + assert(scan_rsp_len <= BLE_SCAN_RSP_LEGACY_DATA_MAX_LEN); + + /* Set BLE transmit header */ + pdulen = BLE_DEV_ADDR_LEN + scan_rsp_len; + hdr = BLE_ADV_PDU_TYPE_SCAN_RSP; + if (advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) { + hdr |= BLE_ADV_PDU_HDR_TXADD_RAND; + } + + *hdr_byte = hdr; + + /* + * The adva in this packet will be the same one that was being advertised + * and is based on the peer identity address in the set advertising + * parameters. If a different peer sends us a scan request (for some reason) + * we will reply with an adva that was not generated based on the local irk + * of the peer sending the scan request. + */ + + /* Construct scan response */ + memcpy(dptr, advsm->adva, BLE_DEV_ADDR_LEN); + if (scan_rsp_len != 0) { + os_mbuf_copydata(advsm->scan_rsp_data, 0, scan_rsp_len, + dptr + BLE_DEV_ADDR_LEN); + } + + return pdulen; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +/** + * Create a scan response PDU + * + * @param advsm + */ +static uint8_t +ble_ll_adv_scan_rsp_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) +{ + struct ble_ll_adv_sm *advsm; + + advsm = pducb_arg; + + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + return ble_ll_adv_scan_rsp_legacy_pdu_make(dptr, pducb_arg, hdr_byte); + } + + return ble_ll_adv_aux_pdu_make(dptr, pducb_arg, hdr_byte); +} + +struct aux_conn_rsp_data { + struct ble_ll_adv_sm *advsm; + uint8_t *peer; + uint8_t rxadd; +}; + +/** + * Create a AUX connect response PDU + * + * @param advsm + */ +static uint8_t +ble_ll_adv_aux_conn_rsp_pdu_make(uint8_t *dptr, void *pducb_arg, + uint8_t *hdr_byte) +{ + struct aux_conn_rsp_data *rsp_data; + uint8_t pdulen; + uint8_t ext_hdr_len; + uint8_t ext_hdr_flags; + uint8_t hdr; + + rsp_data = pducb_arg; + + /* flags,AdvA and TargetA */ + ext_hdr_len = BLE_LL_EXT_ADV_FLAGS_SIZE + BLE_LL_EXT_ADV_ADVA_SIZE + + BLE_LL_EXT_ADV_TARGETA_SIZE; + ext_hdr_flags = (1 << BLE_LL_EXT_ADV_ADVA_BIT); + ext_hdr_flags |= (1 << BLE_LL_EXT_ADV_TARGETA_BIT); + + pdulen = BLE_LL_EXT_ADV_HDR_LEN + ext_hdr_len; + + /* Set BLE transmit header */ + hdr = BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP; + if (rsp_data->rxadd) { + hdr |= BLE_ADV_PDU_HDR_RXADD_MASK; + } + if (rsp_data->advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) { + hdr |= BLE_ADV_PDU_HDR_TXADD_MASK; + } + + *hdr_byte = hdr; + + /* ext hdr len and adv mode (00b) */ + dptr[0] = ext_hdr_len; + dptr += 1; + + /* ext hdr flags */ + dptr[0] = ext_hdr_flags; + dptr += 1; + + memcpy(dptr, rsp_data->advsm->adva, BLE_LL_EXT_ADV_ADVA_SIZE); + dptr += BLE_LL_EXT_ADV_ADVA_SIZE; + + memcpy(dptr, rsp_data->peer, BLE_LL_EXT_ADV_TARGETA_SIZE); + dptr += BLE_LL_EXT_ADV_ADVA_SIZE; + + return pdulen; +} +#endif + +/** + * Called to indicate the advertising event is over. + * + * Context: Interrupt + * + * @param advsm + * + */ +static void +ble_ll_adv_tx_done(void *arg) +{ + struct ble_ll_adv_sm *advsm; + + /* reset power to max after advertising */ + ble_phy_txpwr_set(MYNEWT_VAL(BLE_LL_TX_PWR_DBM)); + + advsm = (struct ble_ll_adv_sm *)arg; + + ble_ll_trace_u32x2(BLE_LL_TRACE_ID_ADV_TXDONE, advsm->adv_instance, + advsm->flags & BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (ble_ll_adv_active_chanset_is_pri(advsm)) { + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); + } else if (ble_ll_adv_active_chanset_is_sec(advsm)) { + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev); + } else { + assert(0); + } +#else + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); +#endif + + ble_ll_state_set(BLE_LL_STATE_STANDBY); + + ble_ll_adv_active_chanset_clear(advsm); + + /* We no longer have a current state machine */ + g_ble_ll_cur_adv_sm = NULL; +} + +/* + * Called when an advertising event has been removed from the scheduler + * without being run. + */ +void +ble_ll_adv_event_rmvd_from_sched(struct ble_ll_adv_sm *advsm) +{ + /* + * Need to set advertising channel to final chan so new event gets + * scheduled. + */ + advsm->adv_chan = ble_ll_adv_final_chan(advsm); + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) +/* + * Called when a periodic event has been removed from the scheduler + * without being run. + */ +void +ble_ll_adv_periodic_rmvd_from_sched(struct ble_ll_adv_sm *advsm) +{ + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_periodic_txdone_ev); +} +#endif + +/** + * This is the scheduler callback (called from interrupt context) which + * transmits an advertisement. + * + * Context: Interrupt (scheduler) + * + * @param sch + * + * @return int + */ +static int +ble_ll_adv_tx_start_cb(struct ble_ll_sched_item *sch) +{ + int rc; + uint8_t end_trans; + uint32_t txstart; + struct ble_ll_adv_sm *advsm; + + /* Get the state machine for the event */ + advsm = (struct ble_ll_adv_sm *)sch->cb_arg; + + /* Set the current advertiser */ + g_ble_ll_cur_adv_sm = advsm; + + ble_ll_adv_active_chanset_set_pri(advsm); + + if ((advsm->flags & BLE_LL_ADV_SM_FLAG_NEW_ADV_DATA) || + (advsm->flags & BLE_LL_ADV_SM_FLAG_NEW_SCAN_RSP_DATA)) { + goto adv_tx_done; + } + + /* Set the power */ + ble_phy_txpwr_set(advsm->adv_txpwr); + + /* Set channel */ + rc = ble_phy_setchan(advsm->adv_chan, BLE_ACCESS_ADDR_ADV, BLE_LL_CRCINIT_ADV); + assert(rc == 0); + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + /* Set phy mode */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + ble_phy_mode_set(BLE_PHY_MODE_1M, BLE_PHY_MODE_1M); + } else { + ble_phy_mode_set(advsm->pri_phy, advsm->pri_phy); + } +#else + ble_phy_mode_set(BLE_PHY_MODE_1M, BLE_PHY_MODE_1M); +#endif +#endif + + /* Set transmit start time. */ + txstart = sch->start_time + g_ble_ll_sched_offset_ticks; + rc = ble_phy_tx_set_start_time(txstart, sch->remainder); + if (rc) { + STATS_INC(ble_ll_stats, adv_late_starts); + goto adv_tx_done; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + ble_phy_encrypt_disable(); +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + advsm->adv_rpa_index = -1; + if (ble_ll_resolv_enabled()) { + ble_phy_resolv_list_enable(); + } else { + ble_phy_resolv_list_disable(); + } +#endif + + /* We switch to RX after connectable or scannable legacy packets. */ + if ((advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) && + ((advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) || + (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE))) { + end_trans = BLE_PHY_TRANSITION_TX_RX; + ble_phy_set_txend_cb(NULL, NULL); + } else { + end_trans = BLE_PHY_TRANSITION_NONE; + ble_phy_set_txend_cb(ble_ll_adv_tx_done, advsm); + } + + /* Transmit advertisement */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + rc = ble_phy_tx(ble_ll_adv_pdu_make, advsm, end_trans); +#else + rc = ble_phy_tx(ble_ll_adv_legacy_pdu_make, advsm, end_trans); +#endif + if (rc) { + goto adv_tx_done; + } + + /* Enable/disable whitelisting based on filter policy */ + if (advsm->adv_filter_policy != BLE_HCI_ADV_FILT_NONE) { + ble_ll_whitelist_enable(); + } else { + ble_ll_whitelist_disable(); + } + + /* Set link layer state to advertising */ + ble_ll_state_set(BLE_LL_STATE_ADV); + + /* Count # of adv. sent */ + STATS_INC(ble_ll_stats, adv_txg); + + return BLE_LL_SCHED_STATE_RUNNING; + +adv_tx_done: + ble_ll_adv_tx_done(advsm); + return BLE_LL_SCHED_STATE_DONE; +} + +static void +ble_ll_adv_set_sched(struct ble_ll_adv_sm *advsm) +{ + uint32_t max_usecs; + struct ble_ll_sched_item *sch; + + sch = &advsm->adv_sch; + sch->cb_arg = advsm; + sch->sched_cb = ble_ll_adv_tx_start_cb; + sch->sched_type = BLE_LL_SCHED_TYPE_ADV; + + /* Set end time to maximum time this schedule item may take */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + max_usecs = ble_ll_pdu_tx_time_get(advsm->adv_pdu_len, BLE_PHY_MODE_1M); + + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { + max_usecs += BLE_LL_SCHED_DIRECT_ADV_MAX_USECS; + } else if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { + max_usecs += BLE_LL_SCHED_ADV_MAX_USECS; + } + } else { + /* + * In ADV_EXT_IND we always set only ADI and AUX so the payload length + * is always 7 bytes. + */ + max_usecs = ble_ll_pdu_tx_time_get(7, advsm->pri_phy); + } +#else + max_usecs = ble_ll_pdu_tx_time_get(advsm->adv_pdu_len, BLE_PHY_MODE_1M); + + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { + max_usecs += BLE_LL_SCHED_DIRECT_ADV_MAX_USECS; + } else if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { + max_usecs += BLE_LL_SCHED_ADV_MAX_USECS; + } +#endif + + sch->start_time = advsm->adv_pdu_start_time - g_ble_ll_sched_offset_ticks; + sch->remainder = 0; + sch->end_time = advsm->adv_pdu_start_time + + ble_ll_usecs_to_ticks_round_up(max_usecs); +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +static int +ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item *sch) +{ + int rc; + uint8_t end_trans; + uint32_t txstart; + struct ble_ll_adv_sm *advsm; + ble_phy_tx_pducb_t pducb; + struct ble_ll_adv_aux *aux; + + /* Get the state machine for the event */ + advsm = (struct ble_ll_adv_sm *)sch->cb_arg; + + /* Set the current advertiser */ + g_ble_ll_cur_adv_sm = advsm; + + ble_ll_adv_active_chanset_set_sec(advsm); + + /* Set the power */ + ble_phy_txpwr_set(advsm->adv_txpwr); + + /* Set channel */ + aux = AUX_CURRENT(advsm); + rc = ble_phy_setchan(aux->chan, BLE_ACCESS_ADDR_ADV, + BLE_LL_CRCINIT_ADV); + assert(rc == 0); + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + /* Set phy mode */ + ble_phy_mode_set(advsm->sec_phy, advsm->sec_phy); +#endif + + /* Set transmit start time. */ + txstart = sch->start_time + g_ble_ll_sched_offset_ticks; + rc = ble_phy_tx_set_start_time(txstart, sch->remainder); + if (rc) { + STATS_INC(ble_ll_stats, adv_late_starts); + goto adv_tx_done; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + ble_phy_encrypt_disable(); +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + advsm->adv_rpa_index = -1; + if (ble_ll_resolv_enabled()) { + ble_phy_resolv_list_enable(); + } else { + ble_phy_resolv_list_disable(); + } +#endif + + /* Set phy mode based on type of advertisement */ + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { + end_trans = BLE_PHY_TRANSITION_TX_RX; + ble_phy_set_txend_cb(NULL, NULL); + pducb = ble_ll_adv_aux_pdu_make; + } else if ((advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) && + advsm->aux_first_pdu) { + end_trans = BLE_PHY_TRANSITION_TX_RX; + ble_phy_set_txend_cb(NULL, NULL); + pducb = ble_ll_adv_aux_scannable_pdu_make; + } else { + end_trans = BLE_PHY_TRANSITION_NONE; + ble_phy_set_txend_cb(ble_ll_adv_tx_done, advsm); + pducb = ble_ll_adv_aux_pdu_make; + } + + /* Transmit advertisement */ + rc = ble_phy_tx(pducb, advsm, end_trans); + if (rc) { + goto adv_tx_done; + } + + /* Enable/disable whitelisting based on filter policy */ + if (advsm->adv_filter_policy != BLE_HCI_ADV_FILT_NONE) { + ble_ll_whitelist_enable(); + } else { + ble_ll_whitelist_disable(); + } + + /* Set link layer state to advertising */ + ble_ll_state_set(BLE_LL_STATE_ADV); + + /* Count # of adv. sent */ + STATS_INC(ble_ll_stats, adv_txg); + + return BLE_LL_SCHED_STATE_RUNNING; + +adv_tx_done: + ble_ll_adv_tx_done(advsm); + return BLE_LL_SCHED_STATE_DONE; +} + +static uint8_t +ble_ll_adv_aux_scannable_pdu_payload_len(struct ble_ll_adv_sm *advsm) +{ + uint8_t len; + + /* Flags, ADI always */ + len = BLE_LL_EXT_ADV_HDR_LEN + BLE_LL_EXT_ADV_FLAGS_SIZE + + BLE_LL_EXT_ADV_DATA_INFO_SIZE; + + /* AdvA if not anonymous */ + if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV)) { + len += BLE_LL_EXT_ADV_ADVA_SIZE; + } + + /* TargetA only for directed */ + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { + len += BLE_LL_EXT_ADV_TARGETA_SIZE; + } + + /* TxPower if configured */ + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR) { + len += BLE_LL_EXT_ADV_TX_POWER_SIZE; + } + + return len; +} + +static void +ble_ll_adv_aux_calculate(struct ble_ll_adv_sm *advsm, + struct ble_ll_adv_aux *aux, uint16_t aux_data_offset) +{ + uint16_t rem_aux_data_len; + uint8_t hdr_len; + bool chainable; + + assert(!aux->sch.enqueued); + assert((AUX_DATA_LEN(advsm) > aux_data_offset) || + (AUX_DATA_LEN(advsm) == 0 && aux_data_offset == 0)); + + aux->aux_data_offset = aux_data_offset; + aux->aux_data_len = 0; + aux->payload_len = 0; + aux->ext_hdr = 0; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) + aux->chan = ble_ll_utils_calc_dci_csa2(advsm->event_cntr++, + advsm->channel_id, + g_ble_ll_conn_params.num_used_chans, + g_ble_ll_conn_params.master_chan_map); +#else + aux->chan = ble_ll_utils_remapped_channel(rand() % BLE_PHY_NUM_DATA_CHANS, + g_ble_ll_conn_params.master_chan_map); +#endif + + rem_aux_data_len = AUX_DATA_LEN(advsm) - aux_data_offset; + chainable = !(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE); + + hdr_len = BLE_LL_EXT_ADV_HDR_LEN; + + if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE)) { + /* ADI */ + aux->ext_hdr |= (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT); + hdr_len += BLE_LL_EXT_ADV_DATA_INFO_SIZE; + } + + /* AdvA for 1st PDU in chain (i.e. AUX_ADV_IND or AUX_SCAN_RSP) */ + if (aux_data_offset == 0 && + !(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV)) { + aux->ext_hdr |= (1 << BLE_LL_EXT_ADV_ADVA_BIT); + hdr_len += BLE_LL_EXT_ADV_ADVA_SIZE; + } + + /* Note: this function does not calculate AUX_ADV_IND when advertising is + * scannable. Instead it is calculated in ble_ll_adv_aux_schedule_first(). + * + * However this function calculates length of AUX_SCAN_RSP and according + * to BT 5.0 Vol 6 Part B, 2.3.2.3, TargetA shall not be include there. + * + * This is why TargetA is added to all directed advertising here unless it + * is scannable one. + * + * Note. TargetA shall not be also in AUX_CHAIN_IND + */ + if (aux_data_offset == 0 && + (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) && + !(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE)) { + aux->ext_hdr |= (1 << BLE_LL_EXT_ADV_TARGETA_BIT); + hdr_len += BLE_LL_EXT_ADV_TARGETA_SIZE; + } + + /* TxPower if configured. + * Note: TxPower should not be be present in AUX_CHAIN_IND + */ + if (aux_data_offset == 0 && + (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR)) { + aux->ext_hdr |= (1 << BLE_LL_EXT_ADV_TX_POWER_BIT); + hdr_len += BLE_LL_EXT_ADV_TX_POWER_SIZE; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + /* SyncInfo for 1st PDU in chain (i.e. AUX_ADV_IND only) if periodic + * advertising is enabled + */ + if (aux_data_offset == 0 && advsm->periodic_adv_active) { + aux->ext_hdr |= (1 << BLE_LL_EXT_ADV_SYNC_INFO_BIT); + hdr_len += BLE_LL_EXT_ADV_SYNC_INFO_SIZE; + } +#endif + + /* if we have any fields in ext header we need to add flags, note that Aux + * PTR is handled later and it will account for flags if needed + */ + if (aux->ext_hdr) { + hdr_len += BLE_LL_EXT_ADV_FLAGS_SIZE; + } + + /* AdvData always */ + aux->aux_data_len = min(BLE_LL_MAX_PAYLOAD_LEN - hdr_len, rem_aux_data_len); + + /* AuxPtr if there are more AdvData remaining that we can fit here */ + if (chainable && (rem_aux_data_len > aux->aux_data_len)) { + /* adjust for flags that needs to be added if AuxPtr is only field + * in Extended Header + */ + if (!aux->ext_hdr) { + hdr_len += BLE_LL_EXT_ADV_FLAGS_SIZE; + aux->aux_data_len -= BLE_LL_EXT_ADV_FLAGS_SIZE; + } + + aux->ext_hdr |= (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT); + hdr_len += BLE_LL_EXT_ADV_AUX_PTR_SIZE; + aux->aux_data_len -= BLE_LL_EXT_ADV_AUX_PTR_SIZE; + + /* PDU payload should be full if chained */ + assert(hdr_len + aux->aux_data_len == BLE_LL_MAX_PAYLOAD_LEN); + } + + aux->payload_len = hdr_len + aux->aux_data_len; +} + +static void +ble_ll_adv_aux_scheduled(struct ble_ll_adv_sm *advsm, uint32_t sch_start, + void *arg) +{ + struct ble_ll_adv_aux *aux = arg; + + aux->start_time = sch_start + g_ble_ll_sched_offset_ticks; +} + +static void +ble_ll_adv_aux_schedule_next(struct ble_ll_adv_sm *advsm) +{ + struct ble_ll_adv_aux *aux; + struct ble_ll_adv_aux *aux_next; + struct ble_ll_sched_item *sch; + uint16_t rem_aux_data_len; + uint16_t next_aux_data_offset; + uint32_t max_usecs; + + assert(advsm->aux_active); + + aux = AUX_CURRENT(advsm); + aux_next = AUX_NEXT(advsm); + + assert(!aux_next->sch.enqueued); + + /* + * Do not schedule next aux if current aux is no longer scheduled since we + * do not have reference time for scheduling. + */ + if (!aux->sch.enqueued) { + return; + } + + /* + * Do not schedule next aux if current aux does not have AuxPtr in extended + * header as this means we do not need subsequent ADV_CHAIN_IND to be sent. + */ + if (!(aux->ext_hdr & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT))) { + return; + } + + next_aux_data_offset = aux->aux_data_offset + aux->aux_data_len; + + assert(AUX_DATA_LEN(advsm) >= next_aux_data_offset); + + rem_aux_data_len = AUX_DATA_LEN(advsm) - next_aux_data_offset; + assert(rem_aux_data_len > 0); + + ble_ll_adv_aux_calculate(advsm, aux_next, next_aux_data_offset); + max_usecs = ble_ll_pdu_tx_time_get(aux_next->payload_len, advsm->sec_phy); + + aux_next->start_time = aux->sch.end_time + + ble_ll_usecs_to_ticks_round_up(BLE_LL_MAFS + MYNEWT_VAL(BLE_LL_SCHED_AUX_CHAIN_MAFS_DELAY)); + + sch = &aux_next->sch; + sch->start_time = aux_next->start_time - g_ble_ll_sched_offset_ticks; + sch->remainder = 0; + sch->end_time = aux_next->start_time + + ble_ll_usecs_to_ticks_round_up(max_usecs); + ble_ll_sched_adv_new(&aux_next->sch, ble_ll_adv_aux_scheduled, aux_next); + + /* + * In case duration is set for advertising set we need to check if newly + * scheduled aux will fit inside duration. If not, remove it from scheduler + * so advertising will stop after current aux. + */ + if (advsm->duration && (aux_next->sch.end_time > advsm->adv_end_time)) { + ble_ll_sched_rmv_elem(&aux_next->sch); + } +} + +static void +ble_ll_adv_aux_schedule_first(struct ble_ll_adv_sm *advsm) +{ + struct ble_ll_adv_aux *aux; + struct ble_ll_sched_item *sch; + uint32_t max_usecs; + + assert(!advsm->aux_active); + assert(!advsm->aux[0].sch.enqueued); + assert(!advsm->aux[1].sch.enqueued); + + advsm->aux_active = 1; + advsm->aux_index = 0; + advsm->aux_first_pdu = 1; + advsm->aux_not_scanned = 0; + + aux = AUX_CURRENT(advsm); + ble_ll_adv_aux_calculate(advsm, aux, 0); + + /* Set end time to maximum time this schedule item may take */ + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { + max_usecs = ble_ll_pdu_tx_time_get(aux->payload_len, advsm->sec_phy) + + BLE_LL_IFS + + /* AUX_CONN_REQ */ + ble_ll_pdu_tx_time_get(34 + 14, advsm->sec_phy) + + BLE_LL_IFS + + /* AUX_CONN_RSP */ + ble_ll_pdu_tx_time_get(14, advsm->sec_phy); + } else if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) { + /* For scannable advertising we need to calculate how much time we + * need for AUX_ADV_IND along with AUX_SCAN_REQ, AUX_SCAN_RSP and + * IFS in between. + * + * Note: + * 1. aux->payload_len, which calculated by above ble_ll_adv_aux_calulcate(), + * contains AUX_SCAN_RSP length. + * 2. length of AUX_ADV_IND is calculated by special function: + * ble_ll_adv_aux_scannable_pdu_payload_len() + */ + max_usecs = ble_ll_pdu_tx_time_get(ble_ll_adv_aux_scannable_pdu_payload_len(advsm), + advsm->sec_phy) + + BLE_LL_IFS + + /* AUX_SCAN_REQ */ + ble_ll_pdu_tx_time_get(12, advsm->sec_phy) + + BLE_LL_IFS + + /* AUX_SCAN_RSP */ + ble_ll_pdu_tx_time_get(aux->payload_len, advsm->sec_phy); + } else { + max_usecs = ble_ll_pdu_tx_time_get(aux->payload_len, advsm->sec_phy); + } + + sch = &aux->sch; + sch->start_time = aux->start_time - g_ble_ll_sched_offset_ticks; + sch->remainder = 0; + sch->end_time = aux->start_time + ble_ll_usecs_to_ticks_round_up(max_usecs); + ble_ll_sched_adv_new(sch, ble_ll_adv_aux_scheduled, aux); +} + +static void +ble_ll_adv_aux_set_start_time(struct ble_ll_adv_sm *advsm) +{ + static const uint8_t bits[8] = {0, 1, 1, 2, 1, 2, 2, 3}; + struct ble_ll_sched_item *sched = &advsm->adv_sch; + uint32_t adv_pdu_dur; + uint32_t adv_event_dur; + uint8_t chans; + + assert(!advsm->aux_active); + assert(!advsm->aux[0].sch.enqueued); + assert(!advsm->aux[1].sch.enqueued); + + assert(advsm->adv_chanmask > 0 && + advsm->adv_chanmask <= BLE_HCI_ADV_CHANMASK_DEF); + + chans = bits[advsm->adv_chanmask]; + + /* + * We want to schedule auxiliary packet as soon as possible after the end + * of advertising event, but no sooner than T_MAFS. The interval between + * advertising packets is 250 usecs (8.19 ticks) on LE Coded and a bit less + * on 1M, but it can vary a bit due to scheduling which we can't really + * control. Since we round ticks up for both interval and T_MAFS, we still + * have some margin here. The worst thing that can happen is that we skip + * last advertising packet which is not a bit problem so leave it as-is, no + * need to make code more complicated. + */ + + /* + * XXX: this could be improved if phy has TX-TX transition with controlled + * or predefined interval, but since it makes advertising code even + * more complicated let's skip it for now... + */ + + adv_pdu_dur = (int32_t)(sched->end_time - sched->start_time) - + g_ble_ll_sched_offset_ticks; + + /* 9 is 8.19 ticks rounded up - see comment above */ + adv_event_dur = (adv_pdu_dur * chans) + (9 * (chans - 1)); + + advsm->aux[0].start_time = advsm->adv_event_start_time + adv_event_dur + + ble_ll_usecs_to_ticks_round_up(BLE_LL_MAFS + MYNEWT_VAL(BLE_LL_SCHED_AUX_MAFS_DELAY)); +} + +static void +ble_ll_adv_aux_schedule(struct ble_ll_adv_sm *advsm) +{ + /* + * For secondary channel we always start by scheduling two consecutive + * auxiliary packets at once. Then, after sending one packet we try to + * schedule another one as long as there are some data left to send. This + * is to make sure we can always calculate AuxPtr to subsequent packet + * without need to scheduled it in an interrupt. + */ + + ble_ll_adv_aux_set_start_time(advsm); + ble_ll_adv_aux_schedule_first(advsm); + ble_ll_adv_aux_schedule_next(advsm); + + /* + * In case duration is set for advertising set we need to check if at least + * 1st aux will fit inside duration. If not, stop advertising now so we do + * not start extended advertising event which we cannot finish in time. + */ + if (advsm->duration && + (AUX_CURRENT(advsm)->sch.end_time > advsm->adv_end_time)) { + ble_ll_adv_sm_stop_timeout(advsm); + } +} +#endif + +/** + * Called when advertising need to be halted. This normally should not be called + * and is only called when a scheduled item executes but advertising is still + * running. + * + * Context: Interrupt + */ +void +ble_ll_adv_halt(void) +{ + struct ble_ll_adv_sm *advsm; + + if (g_ble_ll_cur_adv_sm != NULL) { + advsm = g_ble_ll_cur_adv_sm; + + ble_ll_trace_u32(BLE_LL_TRACE_ID_ADV_HALT, advsm->adv_instance); + + ble_phy_txpwr_set(MYNEWT_VAL(BLE_LL_TX_PWR_DBM)); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + if (advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING) { + ble_ll_adv_flags_clear(advsm, + BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING); + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, + &advsm->adv_periodic_txdone_ev); + ble_ll_state_set(BLE_LL_STATE_STANDBY); + g_ble_ll_cur_adv_sm = NULL; + return; + } +#endif + + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)) { + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev); + } +#endif + + ble_ll_state_set(BLE_LL_STATE_STANDBY); + ble_ll_adv_active_chanset_clear(g_ble_ll_cur_adv_sm); + g_ble_ll_cur_adv_sm = NULL; + } else { + ble_ll_trace_u32(BLE_LL_TRACE_ID_ADV_HALT, UINT32_MAX); + } +} + +/** + * Called by the HCI command parser when a set advertising parameters command + * has been received. + * + * Context: Link Layer task (HCI command parser) + * + * @param cmd + * + * @return int + */ +int +ble_ll_adv_set_adv_params(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_set_adv_params_cp *cmd = (const void *) cmdbuf; + struct ble_ll_adv_sm *advsm; + uint8_t adv_filter_policy; + uint16_t adv_itvl_min; + uint16_t adv_itvl_max; + uint16_t props; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + advsm = &g_ble_ll_adv_sm[0]; + if (advsm->adv_enabled) { + return BLE_ERR_CMD_DISALLOWED; + } + + /* Make sure intervals are OK (along with advertising type */ + adv_itvl_min = le16toh(cmd->min_interval); + adv_itvl_max = le16toh(cmd->max_interval); + + /* + * Get the filter policy now since we will ignore it if we are doing + * directed advertising + */ + adv_filter_policy = cmd->filter_policy; + + switch (cmd->type) { + case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD: + adv_filter_policy = BLE_HCI_ADV_FILT_NONE; + memcpy(advsm->peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN); + + /* Ignore min/max interval */ + adv_itvl_min = 0; + adv_itvl_max = 0; + + props = BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_HD_DIR ; + break; + case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD: + adv_filter_policy = BLE_HCI_ADV_FILT_NONE; + memcpy(advsm->peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN); + + props = BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_LD_DIR ; + break; + case BLE_HCI_ADV_TYPE_ADV_IND: + props = BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_IND; + break; + case BLE_HCI_ADV_TYPE_ADV_NONCONN_IND: + props = BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_NONCONN; + break; + case BLE_HCI_ADV_TYPE_ADV_SCAN_IND: + props = BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_SCAN; + break; + default: + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Make sure intervals values are valid + * (HD directed advertising ignores those parameters) + */ + if (!(props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED)) { + if ((adv_itvl_min > adv_itvl_max) || + (adv_itvl_min < BLE_HCI_ADV_ITVL_MIN) || + (adv_itvl_min > BLE_HCI_ADV_ITVL_MAX) || + (adv_itvl_max < BLE_HCI_ADV_ITVL_MIN) || + (adv_itvl_max > BLE_HCI_ADV_ITVL_MAX)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + } + + if ((cmd->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) || + (cmd->peer_addr_type > BLE_HCI_ADV_PEER_ADDR_MAX)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + advsm->adv_txpwr = MYNEWT_VAL(BLE_LL_TX_PWR_DBM); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + if (cmd->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) { + /* Copy peer address */ + memcpy(advsm->peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN); + } +#else + /* If we dont support privacy some address types wont work */ + if (cmd->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) { + return BLE_ERR_UNSUPPORTED; + } +#endif + + /* There are only three adv channels, so check for any outside the range */ + if (((cmd->chan_map & 0xF8) != 0) || (cmd->chan_map == 0)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Check for valid filter policy */ + if (adv_filter_policy > BLE_HCI_ADV_FILT_MAX) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Fill out rest of advertising state machine */ + advsm->own_addr_type = cmd->own_addr_type; + advsm->peer_addr_type = cmd->peer_addr_type; + advsm->adv_filter_policy = adv_filter_policy; + advsm->adv_chanmask = cmd->chan_map; + advsm->adv_itvl_min = adv_itvl_min; + advsm->adv_itvl_max = adv_itvl_max; + advsm->props = props; + + return 0; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +static void +ble_ll_adv_update_did(struct ble_ll_adv_sm *advsm) +{ + uint16_t old_adi = advsm->adi; + + /* + * The Advertising DID for a given advertising set shall be initialized + * with a randomly chosen value. Whenever the Host provides new advertising + * data or scan response data for a given advertising set (whether it is the + * same as the previous data or not), the Advertising DID shall be updated. + * The new value shall be a randomly chosen value that is not the same as + * the previously used value. + */ + do { + advsm->adi = (advsm->adi & 0xf000) | (rand() & 0x0fff); + } while (old_adi == advsm->adi); +} +#endif + +static void +ble_ll_adv_update_adv_scan_rsp_data(struct ble_ll_adv_sm *advsm) +{ + if (!(advsm->flags & BLE_LL_ADV_SM_FLAG_NEW_ADV_DATA) && + !(advsm->flags & BLE_LL_ADV_SM_FLAG_NEW_SCAN_RSP_DATA)) { + return; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (advsm->aux_active) { + return; + } +#endif + + if (advsm->flags & BLE_LL_ADV_SM_FLAG_NEW_ADV_DATA) { + if (advsm->new_adv_data) { + os_mbuf_free_chain(advsm->adv_data); + advsm->adv_data = advsm->new_adv_data; + advsm->new_adv_data = NULL; + } + ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_NEW_ADV_DATA); + } else if (advsm->flags & BLE_LL_ADV_SM_FLAG_NEW_SCAN_RSP_DATA) { + os_mbuf_free_chain(advsm->scan_rsp_data); + advsm->scan_rsp_data = advsm->new_scan_rsp_data; + advsm->new_scan_rsp_data = NULL; + ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_NEW_SCAN_RSP_DATA); + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + /* DID shall be updated when host provides new advertising data */ + ble_ll_adv_update_did(advsm); +#endif +} + +/** + * Stop advertising state machine + * + * Context: Link Layer task. + * + * @param advsm + */ +static void +ble_ll_adv_sm_stop(struct ble_ll_adv_sm *advsm) +{ + os_sr_t sr; + + if (advsm->adv_enabled) { + ble_ll_rfmgmt_release(); + + /* Remove any scheduled advertising items */ + ble_ll_sched_rmv_elem(&advsm->adv_sch); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + advsm->aux_active = 0; + ble_ll_sched_rmv_elem(&advsm->aux[0].sch); + ble_ll_sched_rmv_elem(&advsm->aux[1].sch); +#endif + + /* Set to standby if we are no longer advertising */ + OS_ENTER_CRITICAL(sr); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if ((g_ble_ll_cur_adv_sm == advsm) && + !(advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING)) { + ble_phy_disable(); + ble_ll_state_set(BLE_LL_STATE_STANDBY); + g_ble_ll_cur_adv_sm = NULL; + ble_ll_scan_chk_resume(); + } +#else + if (ble_ll_state_get() == BLE_LL_STATE_ADV) { + ble_phy_disable(); + ble_ll_state_set(BLE_LL_STATE_STANDBY); + g_ble_ll_cur_adv_sm = NULL; + ble_ll_scan_chk_resume(); + } +#endif + OS_EXIT_CRITICAL(sr); + + ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev); +#endif + + /* If there is an event buf we need to free it */ + if (advsm->conn_comp_ev) { + ble_hci_trans_buf_free(advsm->conn_comp_ev); + advsm->conn_comp_ev = NULL; + } + + ble_ll_adv_active_chanset_clear(advsm); + + /* Disable advertising */ + advsm->adv_enabled = 0; + + /* Check if there is outstanding update */ + ble_ll_adv_update_adv_scan_rsp_data(advsm); + } +} + +static void +ble_ll_adv_sm_stop_timeout(struct ble_ll_adv_sm *advsm) +{ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (ble_ll_hci_adv_mode_ext()) { + ble_ll_hci_ev_send_adv_set_terminated(BLE_ERR_DIR_ADV_TMO, + advsm->adv_instance, 0, + advsm->events); + } +#endif + + /* + * For high duty directed advertising we need to send connection + * complete event with proper status + */ + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { + ble_ll_conn_comp_event_send(NULL, BLE_ERR_DIR_ADV_TMO, + advsm->conn_comp_ev, advsm); + advsm->conn_comp_ev = NULL; + } + + /* Disable advertising */ + ble_ll_adv_sm_stop(advsm); +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +static void +ble_ll_adv_sm_stop_limit_reached(struct ble_ll_adv_sm *advsm) +{ + ble_ll_hci_ev_send_adv_set_terminated(BLE_ERR_LIMIT_REACHED, + advsm->adv_instance, 0, + advsm->events); + + /* + * For high duty directed advertising we need to send connection + * complete event with proper status + * + * Spec is a bit unambiguous here since it doesn't define what code should + * be used if HD directed advertising was terminated before timeout due to + * events count limit. For now just use same code as with duration timeout. + */ + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { + ble_ll_conn_comp_event_send(NULL, BLE_ERR_DIR_ADV_TMO, + advsm->conn_comp_ev, advsm); + advsm->conn_comp_ev = NULL; + } + + /* Disable advertising */ + ble_ll_adv_sm_stop(advsm); +} +#endif + +static void +ble_ll_adv_scheduled(struct ble_ll_adv_sm *advsm, uint32_t sch_start, void *arg) +{ + /* The event start time is when we start transmission of the adv PDU */ + advsm->adv_event_start_time = sch_start + g_ble_ll_sched_offset_ticks; + advsm->adv_pdu_start_time = advsm->adv_event_start_time; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + /* this is validated for HD adv so no need to do additional checks here + * duration is in 10ms units + */ + if (advsm->duration) { + advsm->adv_end_time = advsm->adv_event_start_time + + os_cputime_usecs_to_ticks(advsm->duration * 10000); + } +#else + /* Set the time at which we must end directed, high-duty cycle advertising. + */ + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { + advsm->adv_end_time = advsm->adv_event_start_time + + os_cputime_usecs_to_ticks(BLE_LL_ADV_STATE_HD_MAX * 1000); + } +#endif +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) +static uint8_t +ble_ll_adv_sync_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) +{ + struct ble_ll_adv_sm *advsm; + struct ble_ll_adv_sync *sync; + uint8_t adv_mode; + uint8_t pdu_type; + uint8_t ext_hdr_len; + uint32_t offset; + + advsm = pducb_arg; + sync = SYNC_CURRENT(advsm); + + assert(!ble_ll_adv_active_chanset_is_sec(advsm)); + assert(advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING); + + /* It's the same for AUX_SYNC_IND and AUX_CHAIN_IND */ + pdu_type = BLE_ADV_PDU_TYPE_AUX_SYNC_IND; + + /* non-connectable and non-scannable */ + adv_mode = 0; + + ext_hdr_len = sync->payload_len - BLE_LL_EXT_ADV_HDR_LEN - sync->sync_data_len; + dptr[0] = (adv_mode << 6) | ext_hdr_len; + dptr += 1; + + /* only put flags if needed */ + if (sync->ext_hdr) { + dptr[0] = sync->ext_hdr; + dptr += 1; + } + + if (sync->ext_hdr & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) { + if (!SYNC_NEXT(advsm)->sch.enqueued) { + /* + * Trim data here in case we do not have next sync scheduled. This + * can happen if next sync was outside advertising set period and + * was removed from scheduler. + */ + offset = 0; + } else { + offset = os_cputime_ticks_to_usecs(SYNC_NEXT(advsm)->start_time - sync->start_time); + } + + ble_ll_adv_put_aux_ptr(SYNC_NEXT(advsm)->chan, advsm->sec_phy, + offset, dptr); + + dptr += BLE_LL_EXT_ADV_AUX_PTR_SIZE; + } + + if (sync->ext_hdr & (1 << BLE_LL_EXT_ADV_TX_POWER_BIT)) { + dptr[0] = advsm->adv_txpwr + ble_ll_get_tx_pwr_compensation(); + dptr += BLE_LL_EXT_ADV_TX_POWER_SIZE; + } + + if (sync->sync_data_len) { + os_mbuf_copydata(advsm->periodic_adv_data, sync->sync_data_offset, + sync->sync_data_len, dptr); + } + + *hdr_byte = pdu_type; + + return sync->payload_len; +} + + +static void +ble_ll_adv_sync_tx_done(struct ble_ll_adv_sm *advsm) +{ + /* reset power to max after advertising */ + ble_phy_txpwr_set(MYNEWT_VAL(BLE_LL_TX_PWR_DBM)); + + /* for sync we trace a no pri nor sec set */ + ble_ll_trace_u32x2(BLE_LL_TRACE_ID_ADV_TXDONE, advsm->adv_instance, 0); + + assert(advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING); + assert(!ble_ll_adv_active_chanset_is_sec(advsm)); + + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_periodic_txdone_ev); + + ble_ll_state_set(BLE_LL_STATE_STANDBY); + ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING); + + /* We no longer have a current state machine */ + g_ble_ll_cur_adv_sm = NULL; +} + +/** + * Called to indicate the advertising sync event is over. + * + * Context: Interrupt + * + * @param advsm + * + */ +static void +ble_ll_adv_sync_tx_end(void *arg) +{ + struct ble_ll_adv_sm *advsm = arg; + + ble_ll_adv_sync_tx_done(advsm); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) + /* store last sent periodic counter */ + advsm->periodic_event_cntr_last_sent = advsm->periodic_event_cntr; +#endif +} + +static int +ble_ll_adv_sync_tx_start_cb(struct ble_ll_sched_item *sch) +{ + int rc; + uint32_t txstart; + struct ble_ll_adv_sm *advsm; + struct ble_ll_adv_sync *sync; + + /* Get the state machine for the event */ + advsm = (struct ble_ll_adv_sm *)sch->cb_arg; + + /* Set the current advertiser */ + g_ble_ll_cur_adv_sm = advsm; + + ble_ll_adv_active_chanset_clear(advsm); + ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING); + + /* Set the power */ + ble_phy_txpwr_set(advsm->adv_txpwr); + + /* Set channel */ + sync = SYNC_CURRENT(advsm); + rc = ble_phy_setchan(sync->chan, advsm->periodic_access_addr, + advsm->periodic_crcinit); + + assert(rc == 0); + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + /* Set phy mode */ + ble_phy_mode_set(advsm->sec_phy, advsm->sec_phy); +#endif + + /* Set transmit start time. */ + txstart = sch->start_time + g_ble_ll_sched_offset_ticks; + rc = ble_phy_tx_set_start_time(txstart, sch->remainder); + if (rc) { + STATS_INC(ble_ll_stats, adv_late_starts); + goto adv_tx_done; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + ble_phy_encrypt_disable(); +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + ble_phy_resolv_list_disable(); +#endif + + /* Transmit advertisement */ + ble_phy_set_txend_cb(ble_ll_adv_sync_tx_end, advsm); + rc = ble_phy_tx(ble_ll_adv_sync_pdu_make, advsm, BLE_PHY_TRANSITION_NONE); + if (rc) { + goto adv_tx_done; + } + + /* disable whitelisting, we are always non-connectable non-scannable */ + ble_ll_whitelist_disable(); + + /* Set link layer state to advertising */ + ble_ll_state_set(BLE_LL_STATE_ADV); + + /* Count # of adv. sent */ + STATS_INC(ble_ll_stats, adv_txg); + + return BLE_LL_SCHED_STATE_RUNNING; + +adv_tx_done: + ble_ll_adv_sync_tx_done(advsm); + return BLE_LL_SCHED_STATE_DONE; +} + +static void +ble_ll_adv_sync_calculate(struct ble_ll_adv_sm *advsm, + struct ble_ll_adv_sync *sync, + uint16_t sync_data_offset, + uint8_t chan) +{ + uint16_t rem_sync_data_len; + uint8_t hdr_len; + + assert(!sync->sch.enqueued); + assert((SYNC_DATA_LEN(advsm) > sync_data_offset) || + (SYNC_DATA_LEN(advsm) == 0 && sync_data_offset == 0)); + + sync->sync_data_offset = sync_data_offset; + sync->sync_data_len = 0; + sync->payload_len = 0; + sync->ext_hdr = 0; + sync->chan = chan; + + rem_sync_data_len = SYNC_DATA_LEN(advsm) - sync_data_offset; + + hdr_len = BLE_LL_EXT_ADV_HDR_LEN; + + /* TxPower if configured + * Note: TxPower shall not be present in chain PDU for SYNC + */ + if (sync_data_offset == 0 && + (advsm->periodic_adv_props & BLE_HCI_LE_SET_PERIODIC_ADV_PROP_INC_TX_PWR)) { + sync->ext_hdr |= (1 << BLE_LL_EXT_ADV_TX_POWER_BIT); + hdr_len += BLE_LL_EXT_ADV_TX_POWER_SIZE; + } + + /* if we have any fields in ext header we need to add flags, note that Aux + * PTR is handled later and it will account for flags if needed + * + * This could be handled inside TxPower but lets keep code consistent with + * how Aux calculate works and this also make it easier to add more fields + * into flags if needed in future + */ + if (sync->ext_hdr) { + hdr_len += BLE_LL_EXT_ADV_FLAGS_SIZE; + } + + /* AdvData always */ + sync->sync_data_len = min(BLE_LL_MAX_PAYLOAD_LEN - hdr_len, rem_sync_data_len); + + /* AuxPtr if there are more AdvData remaining that we can fit here */ + if ((rem_sync_data_len > sync->sync_data_len)) { + /* adjust for flags that needs to be added if AuxPtr is only field + * in Extended Header + */ + if (!sync->ext_hdr) { + hdr_len += BLE_LL_EXT_ADV_FLAGS_SIZE; + sync->sync_data_len -= BLE_LL_EXT_ADV_FLAGS_SIZE; + } + + sync->ext_hdr |= (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT); + hdr_len += BLE_LL_EXT_ADV_AUX_PTR_SIZE; + sync->sync_data_len -= BLE_LL_EXT_ADV_AUX_PTR_SIZE; + + /* PDU payload should be full if chained */ + assert(hdr_len + sync->sync_data_len == BLE_LL_MAX_PAYLOAD_LEN); + } + + sync->payload_len = hdr_len + sync->sync_data_len; +} + +static void +ble_ll_adv_periodic_schedule_first(struct ble_ll_adv_sm *advsm, + bool first_pdu) +{ + struct ble_ll_adv_sync *sync; + struct ble_ll_sched_item *sch; + uint32_t sch_start; + uint32_t max_usecs; + uint8_t chan; + int rc; + + assert(!advsm->periodic_sync_active); + assert(!advsm->periodic_sync[0].sch.enqueued); + assert(!advsm->periodic_sync[1].sch.enqueued); + + advsm->periodic_sync_active = 1; + advsm->periodic_sync_index = 0; + + sync = SYNC_CURRENT(advsm); + + /* For first SYNC packet in chain we use separate CSA#2 state to maintain + * freq hopping as advertised in SyncInfo + * + * Preincrement event counter as we later send this in PDU so make sure + * same values are used + */ + chan = ble_ll_utils_calc_dci_csa2(++advsm->periodic_event_cntr, + advsm->periodic_channel_id, + advsm->periodic_num_used_chans, + advsm->periodic_chanmap); + + ble_ll_adv_sync_calculate(advsm, sync, 0, chan); + + /* sync is always non-connectable and non-scannable*/ + max_usecs = ble_ll_pdu_tx_time_get(sync->payload_len, advsm->sec_phy); + + sch = &sync->sch; + + advsm->periodic_adv_event_start_time_remainder += advsm->periodic_adv_itvl_rem_usec; + if (advsm->periodic_adv_event_start_time_remainder >= 31) { + advsm->periodic_adv_event_start_time++; + advsm->periodic_adv_event_start_time_remainder -= 31; + } + + sch->start_time = advsm->periodic_adv_event_start_time; + sch->remainder = advsm->periodic_adv_event_start_time_remainder; + sch->end_time = sch->start_time + ble_ll_usecs_to_ticks_round_up(max_usecs); + sch->start_time -= g_ble_ll_sched_offset_ticks; + + rc = ble_ll_sched_periodic_adv(sch, &sch_start, first_pdu); + if (rc) { + STATS_INC(ble_ll_stats, periodic_adv_drop_event); + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, + &advsm->adv_periodic_txdone_ev); + return; + } + + sync->start_time = sch_start + g_ble_ll_sched_offset_ticks; + + assert(first_pdu || + (sync->start_time == advsm->periodic_adv_event_start_time)); + + /* The event start time is when we start transmission of the SYNC PDU */ + advsm->periodic_adv_event_start_time = sync->start_time; +} + +static void +ble_ll_adv_sync_next_scheduled(struct ble_ll_adv_sm *advsm, uint32_t sch_start, + void *arg) +{ + struct ble_ll_adv_sync *sync = arg; + + sync->start_time = sch_start + g_ble_ll_sched_offset_ticks; +} + +static void +ble_ll_adv_periodic_schedule_next(struct ble_ll_adv_sm *advsm) +{ + struct ble_ll_adv_sync *sync; + struct ble_ll_adv_sync *sync_next; + struct ble_ll_sched_item *sch; + uint16_t rem_sync_data_len; + uint16_t next_sync_data_offset; + uint32_t max_usecs; + uint8_t chan; + + assert(advsm->periodic_sync_active); + + sync = SYNC_CURRENT(advsm); + sync_next = SYNC_NEXT(advsm); + + assert(!sync_next->sch.enqueued); + + /* + * Do not schedule next sync if current sync is no longer scheduled since we + * do not have reference time for scheduling. + */ + if (!sync->sch.enqueued) { + return; + } + + /* + * Do not schedule next sync if current sync does not have AuxPtr in extended + * header as this means we do not need subsequent ADV_CHAIN_IND to be sent. + */ + if (!(sync->ext_hdr & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT))) { + return; + } + + next_sync_data_offset = sync->sync_data_offset + sync->sync_data_len; + + assert(SYNC_DATA_LEN(advsm) >= next_sync_data_offset); + + rem_sync_data_len = SYNC_DATA_LEN(advsm) - next_sync_data_offset; + assert(rem_sync_data_len > 0); + + /* we use separate counter for chaining */ + chan = ble_ll_utils_calc_dci_csa2(advsm->periodic_chain_event_cntr++, + advsm->periodic_channel_id, + advsm->periodic_num_used_chans, + advsm->periodic_chanmap); + + ble_ll_adv_sync_calculate(advsm, sync_next, next_sync_data_offset, chan); + max_usecs = ble_ll_pdu_tx_time_get(sync_next->payload_len, advsm->sec_phy); + + sync_next->start_time = sync->sch.end_time + + ble_ll_usecs_to_ticks_round_up(BLE_LL_MAFS + MYNEWT_VAL(BLE_LL_SCHED_AUX_CHAIN_MAFS_DELAY)); + + sch = &sync_next->sch; + sch->start_time = sync_next->start_time - g_ble_ll_sched_offset_ticks; + + /* adjust for previous packets remainder */ + sch->remainder = sync->sch.remainder; + sch->end_time = sync_next->start_time + + ble_ll_usecs_to_ticks_round_up(max_usecs); + + /* here we can use ble_ll_sched_adv_new as we don't care about timing */ + ble_ll_sched_adv_new(&sync_next->sch, ble_ll_adv_sync_next_scheduled, + sync_next); + + /* if we are pass advertising interval, drop chain */ + if (sch->end_time > advsm->periodic_adv_event_start_time + + advsm->periodic_adv_itvl_ticks) { + STATS_INC(ble_ll_stats, periodic_chain_drop_event); + ble_ll_sched_rmv_elem(&sync->sch); + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, + &advsm->adv_periodic_txdone_ev); + } +} + +static void +ble_ll_adv_sync_schedule(struct ble_ll_adv_sm *advsm, bool first_pdu) +{ + /* + * For secondary channel we always start by scheduling two consecutive + * auxiliary packets at once. Then, after sending one packet we try to + * schedule another one as long as there are some data left to send. This + * is to make sure we can always calculate AuxPtr to subsequent packet + * without need to scheduled it in an interrupt. + */ + + ble_ll_adv_periodic_schedule_first(advsm, first_pdu); + ble_ll_adv_periodic_schedule_next(advsm); +} + +static void +ble_ll_adv_reschedule_periodic_event(struct ble_ll_adv_sm *advsm) +{ + advsm->periodic_adv_event_start_time += advsm->periodic_adv_itvl_ticks; + ble_ll_adv_sync_schedule(advsm, false); +} + +static void +ble_ll_adv_update_periodic_data(struct ble_ll_adv_sm *advsm) +{ + if (!(advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_NEW_DATA)) { + return; + } + + if (advsm->periodic_sync_active) { + return; + } + + if (advsm->periodic_new_data) { + os_mbuf_free_chain(advsm->periodic_adv_data); + advsm->periodic_adv_data = advsm->periodic_new_data; + advsm->periodic_new_data = NULL; + } + + ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_PERIODIC_NEW_DATA); +} + +/** + * Called when periodic packet is txd on secondary channel + * + * Context: Link Layer task. + * + * @param ev + */ +static void +ble_ll_adv_periodic_done(struct ble_ll_adv_sm *advsm) +{ + struct ble_ll_adv_sync *sync; + struct ble_ll_adv_sync *sync_next; + + assert(advsm->periodic_adv_enabled); + assert(advsm->periodic_adv_active); + assert(advsm->periodic_sync_active); + + ble_ll_rfmgmt_release(); + + sync = SYNC_CURRENT(advsm); + sync_next = SYNC_NEXT(advsm); + + /* Remove anything else scheduled for periodic */ + ble_ll_sched_rmv_elem(&sync->sch); + ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_periodic_txdone_ev); + + /* If we have next SYNC scheduled, try to schedule another one */ + if (sync_next->sch.enqueued) { + advsm->periodic_sync_index ^= 1; + ble_ll_adv_periodic_schedule_next(advsm); + return; + } + + /* Check if we need to resume scanning */ + ble_ll_scan_chk_resume(); + + advsm->periodic_sync_active = 0; + ble_ll_adv_update_periodic_data(advsm); + ble_ll_adv_reschedule_periodic_event(advsm); +} + +static void +ble_ll_adv_periodic_event_done(struct ble_npl_event *ev) +{ + ble_ll_adv_periodic_done(ble_npl_event_get_arg(ev)); +} + +static void +ble_ll_adv_sm_start_periodic(struct ble_ll_adv_sm *advsm) +{ + uint32_t usecs; + uint32_t ticks; + + /* + * The Advertising DID is not required to change when a SyncInfo field is + * added to or removed from an advertising set. However, if it does not + * change, then scanners may fail to synchronize to periodic advertising + * because entries in the Advertising DID cache (see Section 4.3.3) mean + * they ignore the advertisements containing the SyncInfo field. Therefore, + * advertisers should update the Advertising DID when a periodic advertising + * train is enabled. + */ + ble_ll_adv_update_did(advsm); + + advsm->periodic_adv_active = 1; + + /* keep channel map since we cannot change it later on */ + memcpy(advsm->periodic_chanmap, g_ble_ll_conn_params.master_chan_map, + BLE_LL_CONN_CHMAP_LEN); + advsm->periodic_num_used_chans = g_ble_ll_conn_params.num_used_chans; + advsm->periodic_event_cntr = 0; + /* for chaining we start with random counter as we share access addr */ + advsm->periodic_chain_event_cntr = rand(); + advsm->periodic_access_addr = ble_ll_utils_calc_access_addr(); + advsm->periodic_channel_id = ((advsm->periodic_access_addr & 0xffff0000) >> 16) ^ + (advsm->periodic_access_addr & 0x0000ffff); + advsm->periodic_crcinit = rand() & 0xffffff; + + usecs = (uint32_t)advsm->periodic_adv_itvl_max * BLE_LL_ADV_PERIODIC_ITVL; + ticks = os_cputime_usecs_to_ticks(usecs); + + advsm->periodic_adv_itvl_rem_usec = (usecs - os_cputime_ticks_to_usecs(ticks)); + if (advsm->periodic_adv_itvl_rem_usec == 31) { + advsm->periodic_adv_itvl_rem_usec = 0; + ticks++; + } + advsm->periodic_adv_itvl_ticks = ticks; + + /* There is no point in starting periodic advertising until next advertising + * event since SyncInfo is needed for synchronization + */ + advsm->periodic_adv_event_start_time_remainder = 0; + advsm->periodic_adv_event_start_time = advsm->adv_pdu_start_time + + os_cputime_usecs_to_ticks(advsm->adv_itvl_usecs + 5000); + + ble_ll_adv_sync_schedule(advsm, true); +} + +static void +ble_ll_adv_sm_stop_periodic(struct ble_ll_adv_sm *advsm) +{ + os_sr_t sr; + + ble_ll_rfmgmt_release(); + + if (!advsm->periodic_adv_active) { + return; + } + + /* + * The Advertising DID is not required to change when a SyncInfo field is + * added to or removed from an advertising set. However, if it does not + * change, then scanners may unnecessary try to synchronize to instance that + * no longer has periodic advertising enabled because entries in the + * Advertising DID cache (see Section 4.3.3) mean they ignore the + * advertisements no longer containing the SyncInfo field. Therefore, + * advertisers should update the Advertising DID when a periodic advertising + * train is disabled. + */ + ble_ll_adv_update_did(advsm); + + /* Remove any scheduled advertising items */ + advsm->periodic_adv_active = 0; + advsm->periodic_sync_active = 0; + ble_ll_sched_rmv_elem(&advsm->periodic_sync[0].sch); + ble_ll_sched_rmv_elem(&advsm->periodic_sync[1].sch); + + /* Set to standby if we are no longer advertising */ + OS_ENTER_CRITICAL(sr); + if ((g_ble_ll_cur_adv_sm == advsm) && + (advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING)) { + ble_phy_disable(); + ble_ll_state_set(BLE_LL_STATE_STANDBY); + g_ble_ll_cur_adv_sm = NULL; + ble_ll_scan_chk_resume(); + } + OS_EXIT_CRITICAL(sr); + + ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING); + + ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, + &advsm->adv_periodic_txdone_ev); + + ble_ll_adv_update_periodic_data(advsm); +} +#endif + +/** + * Start the advertising state machine. This is called when the host sends + * the "enable advertising" command and is not called again while in the + * advertising state. + * + * Context: Link-layer task. + * + * @param advsm Pointer to advertising state machine + * + * @return int + */ +static int +ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm) +{ + uint8_t adv_chan; + uint8_t *addr; + uint8_t *evbuf; + uint32_t start_delay_us; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) + uint32_t access_addr; +#endif + const uint8_t *random_addr; + uint32_t earliest_start_time; + int32_t delta; + + /* only clear flags that are not set from HCI */ + ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_TX_ADD | + BLE_LL_ADV_SM_FLAG_RX_ADD | + BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + random_addr = advsm->adv_random_addr; +#else + random_addr = g_random_addr; +#endif + + if (!ble_ll_is_valid_own_addr_type(advsm->own_addr_type, random_addr)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* + * Get an event with which to send the connection complete event if + * this is connectable + */ + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { + /* We expect this to be NULL but if not we wont allocate one... */ + if (advsm->conn_comp_ev == NULL) { + evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (!evbuf) { + return BLE_ERR_MEM_CAPACITY; + } + advsm->conn_comp_ev = evbuf; + } + } + + /* Set advertising address */ + if ((advsm->own_addr_type & 1) == 0) { + addr = g_dev_addr; + } else { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + addr = advsm->adv_random_addr; +#else + addr = g_random_addr; +#endif + advsm->flags |= BLE_LL_ADV_SM_FLAG_TX_ADD; + } + memcpy(advsm->adva, addr, BLE_DEV_ADDR_LEN); + + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { + memcpy(advsm->initiator_addr, advsm->peer_addr, BLE_DEV_ADDR_LEN); + if (advsm->peer_addr_type & 1) { + advsm->flags |= BLE_LL_ADV_SM_FLAG_RX_ADD; + } + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + /* This will generate an RPA for both initiator addr and adva */ + if (advsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) { + ble_ll_adv_rpa_update(advsm); + } +#endif + + /* Set flag telling us that advertising is enabled */ + advsm->adv_enabled = 1; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) + advsm->event_cntr = 0; + access_addr = ble_ll_utils_calc_access_addr(); + advsm->channel_id = ((access_addr & 0xffff0000) >> 16) ^ + (access_addr & 0x0000ffff); +#endif + + /* Determine the advertising interval we will use */ + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { + /* Set it to max. allowed for high duty cycle advertising */ + advsm->adv_itvl_usecs = BLE_LL_ADV_PDU_ITVL_HD_MS_MAX; + } else { + advsm->adv_itvl_usecs = (uint32_t)advsm->adv_itvl_max; + advsm->adv_itvl_usecs *= BLE_LL_ADV_ITVL; + } + + /* Set first advertising channel */ + adv_chan = ble_ll_adv_first_chan(advsm); + advsm->adv_chan = adv_chan; + + /* + * Scheduling 1st PDU is a bit tricky. + * Earliest possible start time is after RF is enabled so just force RF to + * start here to see when if will be fully enabled - it will be too early, + * but this is the only reliable way to have it enabled on time. + * Next we calculate expected start time (randomize it a bit) and this is + * used to setup start time for scheduler item. + * Then we check if start time for scheduler item (which includes scheduler + * overhead) is no earlier than calculated earliest possible start time and + * adjust scheduler item if necessary. + */ + earliest_start_time = ble_ll_rfmgmt_enable_now(); + + start_delay_us = rand() % (BLE_LL_ADV_DELAY_MS_MAX * 1000); + advsm->adv_pdu_start_time = os_cputime_get32() + + os_cputime_usecs_to_ticks(start_delay_us); + + ble_ll_adv_set_sched(advsm); + + delta = (int32_t)(advsm->adv_sch.start_time - earliest_start_time); + if (delta < 0) { + advsm->adv_sch.start_time -= delta; + advsm->adv_sch.end_time -= delta; + } + + /* This does actual scheduling */ + ble_ll_sched_adv_new(&advsm->adv_sch, ble_ll_adv_scheduled, NULL); + + /* we start periodic before AE since we need PDU start time in SyncInfo */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + if (advsm->periodic_adv_enabled && !advsm->periodic_adv_active) { + ble_ll_adv_sm_start_periodic(advsm); + } +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)) { + ble_ll_adv_aux_schedule(advsm); + } +#endif + + return BLE_ERR_SUCCESS; +} + +/** + * Called when the LE HCI command read advertising channel tx power command + * has been received. Returns the current advertising transmit power. + * + * Context: Link Layer task (HCI command parser) + * + * @return int + */ +int +ble_ll_adv_read_txpwr(uint8_t *rspbuf, uint8_t *rsplen) +{ + struct ble_hci_le_rd_adv_chan_txpwr_rp *rsp = (void *) rspbuf; + + rsp->power_level = MYNEWT_VAL(BLE_LL_TX_PWR_DBM); + + *rsplen = sizeof(*rsp); + return BLE_ERR_SUCCESS; +} + +/** + * Turn advertising on/off. + * + * Context: Link Layer task + * + * @param cmd + * + * @return int + */ +static int +ble_ll_adv_set_enable(uint8_t instance, uint8_t enable, int duration, + uint8_t events) +{ + int rc; + struct ble_ll_adv_sm *advsm; + + advsm = ble_ll_adv_sm_find_configured(instance); + if (!advsm) { + return BLE_ERR_UNK_ADV_INDENT; + } + + rc = BLE_ERR_SUCCESS; + if (enable == 1) { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (advsm->flags & BLE_LL_ADV_SM_FLAG_ADV_DATA_INCOMPLETE) { + return BLE_ERR_CMD_DISALLOWED; + } + + if (ble_ll_hci_adv_mode_ext() && + (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) && + !(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) && + SCAN_RSP_DATA_LEN(advsm) == 0) { + return BLE_ERR_CMD_DISALLOWED; + } + + /* handle specifics of HD dir adv enabled in legacy way */ + if (duration < 0) { + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { + duration = BLE_LL_ADV_STATE_HD_MAX / 10; + } else { + duration = 0; + } + } + advsm->duration = duration; + advsm->events_max = events; + advsm->events = 0; +#endif + + /* If already enabled, do nothing */ + if (!advsm->adv_enabled) { + /* Start the advertising state machine */ + rc = ble_ll_adv_sm_start(advsm); + } + } else if (enable == 0) { + ble_ll_adv_sm_stop(advsm); + } else { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + } + + return rc; +} + +int +ble_ll_hci_adv_set_enable(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_set_adv_enable_cp *cmd = (const void *) cmdbuf; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + return ble_ll_adv_set_enable(0, cmd->enable, -1, 0); +} + +static void +ble_ll_adv_update_data_mbuf(struct os_mbuf **omp, bool new_data, uint16_t maxlen, + const void *data, uint16_t datalen) +{ + struct os_mbuf *om; + int ret; + + om = *omp; + + if (new_data) { + if (om) { + os_mbuf_free_chain(om); + } + + om = os_msys_get_pkthdr(datalen, 0); + if (!om) { + goto done; + } + } + + assert(om); + + if (OS_MBUF_PKTLEN(om) + datalen > maxlen) { + os_mbuf_free_chain(om); + om = NULL; + goto done; + } + + ret = os_mbuf_append(om, data, datalen); + if (ret) { + os_mbuf_free_chain(om); + om = NULL; + } + +done: + *omp = om; +} + +/** + * Set the scan response data that the controller will send. + * + * @param cmd + * @param len + * + * @return int + */ +static int +ble_ll_adv_set_scan_rsp_data(const uint8_t *data, uint8_t datalen, + uint8_t instance, uint8_t operation) +{ + struct ble_ll_adv_sm *advsm; + bool new_data; + + advsm = ble_ll_adv_sm_find_configured(instance); + if (!advsm) { + return BLE_ERR_UNK_ADV_INDENT; + } + + /* check if type of advertising support scan rsp */ + if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE)) { + if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + } + + switch (operation) { + case BLE_HCI_LE_SET_DATA_OPER_COMPLETE: + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + if (datalen > BLE_SCAN_RSP_LEGACY_DATA_MAX_LEN) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + } + + break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + case BLE_HCI_LE_SET_DATA_OPER_LAST: + /* TODO mark scan rsp as complete? */ + /* fall through */ + case BLE_HCI_LE_SET_DATA_OPER_INT: + if (!advsm->scan_rsp_data) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (advsm->adv_enabled) { + return BLE_ERR_CMD_DISALLOWED; + } + + if (!datalen) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + break; + case BLE_HCI_LE_SET_DATA_OPER_FIRST: + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (advsm->adv_enabled) { + return BLE_ERR_CMD_DISALLOWED; + } + + if (!datalen) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + break; +#endif + default: + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + new_data = (operation == BLE_HCI_LE_SET_DATA_OPER_COMPLETE) || + (operation == BLE_HCI_LE_SET_DATA_OPER_FIRST); + + if (advsm->adv_enabled) { + if (advsm->new_scan_rsp_data) { + ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_NEW_SCAN_RSP_DATA); + os_mbuf_free_chain(advsm->new_scan_rsp_data); + advsm->new_scan_rsp_data = NULL; + } + + ble_ll_adv_update_data_mbuf(&advsm->new_scan_rsp_data, new_data, + BLE_ADV_DATA_MAX_LEN, data, datalen); + if (!advsm->new_scan_rsp_data) { + return BLE_ERR_MEM_CAPACITY; + } + ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_NEW_SCAN_RSP_DATA); + } else { + ble_ll_adv_update_data_mbuf(&advsm->scan_rsp_data, new_data, + BLE_SCAN_RSP_DATA_MAX_LEN, data, datalen); + if (!advsm->scan_rsp_data) { + return BLE_ERR_MEM_CAPACITY; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + /* DID shall be updated when host provides new scan response data */ + ble_ll_adv_update_did(advsm); +#endif + } + + return BLE_ERR_SUCCESS; +} + +int +ble_ll_hci_set_scan_rsp_data(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_set_scan_rsp_data_cp *cmd = (const void *) cmdbuf; + + if ((len != sizeof(*cmd)) || (cmd->scan_rsp_len > sizeof(cmd->scan_rsp))) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + return ble_ll_adv_set_scan_rsp_data(cmd->scan_rsp, cmd->scan_rsp_len, 0, + BLE_HCI_LE_SET_DATA_OPER_COMPLETE); +} +/** + * Called by the LL HCI command parser when a set advertising + * data command has been sent from the host to the controller. + * + * @param cmd Pointer to command data + * @param len Length of command data + * + * @return int 0: success; BLE_ERR_INV_HCI_CMD_PARMS otherwise. + */ +static int +ble_ll_adv_set_adv_data(const uint8_t *data, uint8_t datalen, uint8_t instance, + uint8_t operation) +{ + struct ble_ll_adv_sm *advsm; + bool new_data; + + advsm = ble_ll_adv_sm_find_configured(instance); + if (!advsm) { + return BLE_ERR_UNK_ADV_INDENT; + } + + /* check if type of advertising support adv data */ + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { + if (ble_ll_hci_adv_mode_ext()) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + } + } else { + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + } + + switch (operation) { + case BLE_HCI_LE_SET_DATA_OPER_COMPLETE: + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + if (datalen > BLE_ADV_LEGACY_DATA_MAX_LEN) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + } + + ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_ADV_DATA_INCOMPLETE); + + break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + case BLE_HCI_LE_SET_DATA_OPER_UNCHANGED: + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (!advsm->adv_enabled || !ADV_DATA_LEN(advsm) || datalen) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* update DID only */ + ble_ll_adv_update_did(advsm); + return BLE_ERR_SUCCESS; + case BLE_HCI_LE_SET_DATA_OPER_LAST: + ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_ADV_DATA_INCOMPLETE); + /* fall through */ + case BLE_HCI_LE_SET_DATA_OPER_INT: + if (!advsm->adv_data) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (!datalen) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (advsm->adv_enabled) { + return BLE_ERR_CMD_DISALLOWED; + } + break; + case BLE_HCI_LE_SET_DATA_OPER_FIRST: + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (advsm->adv_enabled) { + return BLE_ERR_CMD_DISALLOWED; + } + + if (!datalen) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_ADV_DATA_INCOMPLETE); + break; +#endif + default: + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + new_data = (operation == BLE_HCI_LE_SET_DATA_OPER_COMPLETE) || + (operation == BLE_HCI_LE_SET_DATA_OPER_FIRST); + + if (advsm->adv_enabled) { + if (advsm->new_adv_data) { + ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_NEW_ADV_DATA); + os_mbuf_free_chain(advsm->new_adv_data); + advsm->new_adv_data = NULL; + } + + ble_ll_adv_update_data_mbuf(&advsm->new_adv_data, new_data, + BLE_ADV_DATA_MAX_LEN, data, datalen); + if (!advsm->new_adv_data) { + return BLE_ERR_MEM_CAPACITY; + } + ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_NEW_ADV_DATA); + } else { + ble_ll_adv_update_data_mbuf(&advsm->adv_data, new_data, + BLE_ADV_DATA_MAX_LEN, data, datalen); + if (!advsm->adv_data) { + return BLE_ERR_MEM_CAPACITY; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + /* DID shall be updated when host provides new advertising data */ + ble_ll_adv_update_did(advsm); +#endif + } + + return BLE_ERR_SUCCESS; +} + +int +ble_ll_hci_set_adv_data(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_set_adv_data_cp *cmd = (const void *) cmdbuf; + + if ((len != sizeof(*cmd)) || (cmd->adv_data_len > sizeof(cmd->adv_data))) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + return ble_ll_adv_set_adv_data(cmd->adv_data, cmd->adv_data_len, 0, + BLE_HCI_LE_SET_DATA_OPER_COMPLETE); +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +static bool +pri_phy_valid(uint8_t phy) +{ + switch (phy) { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + case BLE_HCI_LE_PHY_CODED: +#endif + case BLE_HCI_LE_PHY_1M: + return true; + default: + return false; + } +} + +static bool +sec_phy_valid(uint8_t phy) +{ + switch (phy) { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + case BLE_HCI_LE_PHY_CODED: +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) + case BLE_HCI_LE_PHY_2M: +#endif + case BLE_HCI_LE_PHY_1M: + return true; + default: + return false; + } +} + +static struct ble_ll_adv_sm * +ble_ll_adv_sm_get(uint8_t instance) +{ + struct ble_ll_adv_sm *advsm; + int i; + + advsm = ble_ll_adv_sm_find_configured(instance); + if (advsm) { + return advsm; + } + + for (i = 0; i < ARRAY_SIZE(g_ble_ll_adv_sm); i++) { + advsm = &g_ble_ll_adv_sm[i]; + + if (!(advsm->flags & BLE_LL_ADV_SM_FLAG_CONFIGURED)) { + ble_ll_adv_sm_init(advsm); + + /* configured flag is set by caller on success config */ + advsm->adv_instance = instance; + return advsm; + } + } + + return NULL; +} + +int +ble_ll_adv_ext_set_param(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_le_set_ext_adv_params_cp *cmd = (const void *) cmdbuf; + struct ble_hci_le_set_ext_adv_params_rp *rsp = (void *) rspbuf; + struct ble_ll_adv_sm *advsm; + uint32_t adv_itvl_min; + uint32_t adv_itvl_max; + uint16_t props; + int rc; + + if (len != sizeof(*cmd )) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + + advsm = ble_ll_adv_sm_get(cmd->adv_handle); + if (!advsm) { + rc = BLE_ERR_MEM_CAPACITY; + goto done; + } + + if (advsm->adv_enabled) { + rc = BLE_ERR_CMD_DISALLOWED; + goto done; + } + + props = le16toh(cmd->props); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + /* If the Host issues this command when periodic advertising is enabled for + * the specified advertising set and connectable, scannable, legacy, or + * anonymous advertising is specified, the Controller shall return the + * error code Invalid HCI Command Parameters (0x12). + */ + if (advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_CONFIGURED) { + if (advsm->periodic_adv_enabled) { + if (props & (BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE | + BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE | + BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY | + BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV)) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + } + } +#endif + + adv_itvl_min = cmd->pri_itvl_min[2] << 16 | cmd->pri_itvl_min[1] << 8 | + cmd->pri_itvl_min[0]; + adv_itvl_max = cmd->pri_itvl_max[2] << 16 | cmd->pri_itvl_max[1] << 8 | + cmd->pri_itvl_max[0]; + + if (props & ~BLE_HCI_LE_SET_EXT_ADV_PROP_MASK) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + + if (props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + if (ADV_DATA_LEN(advsm) > BLE_ADV_LEGACY_DATA_MAX_LEN || + SCAN_RSP_DATA_LEN(advsm) > BLE_SCAN_RSP_LEGACY_DATA_MAX_LEN) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + + /* if legacy bit is set possible values are limited */ + switch (props) { + case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_IND: + case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_LD_DIR: + case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_HD_DIR: + case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_SCAN: + case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_NONCONN: + break; + default: + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + } else { + /* HD directed advertising allowed only on legacy PDUs */ + if (props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + + /* if ext advertising PDUs are used then it shall not be both + * connectable and scanable + */ + if ((props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) && + (props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE)) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + } + + /* High Duty Directed advertising is special */ + if (props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { + if (ADV_DATA_LEN(advsm) || SCAN_RSP_DATA_LEN(advsm)) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + + /* Ignore min/max interval */ + adv_itvl_min = 0; + adv_itvl_max = 0; + } else { + /* validate intervals for non HD-directed advertising */ + if ((adv_itvl_min > adv_itvl_max) || + (adv_itvl_min < BLE_HCI_ADV_ITVL_MIN) || + (adv_itvl_max < BLE_HCI_ADV_ITVL_MIN)) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + + /* TODO for now limit those to values from legacy advertising + * + * If the primary advertising interval range is outside the advertising + * interval range supported by the Controller, then the Controller shall + * return the error code Unsupported Feature or Parameter Value (0x11). + */ + if ((adv_itvl_min > BLE_HCI_ADV_ITVL_MAX) || + (adv_itvl_max > BLE_HCI_ADV_ITVL_MAX)) { + rc = BLE_ERR_UNSUPPORTED; + goto done; + } + } + + /* There are only three adv channels, so check for any outside the range */ + if (((cmd->pri_chan_map & 0xF8) != 0) || (cmd->pri_chan_map == 0)) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + + if (cmd->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + +#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + /* If we dont support privacy some address types wont work */ + if (cmd->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) { + rc = BLE_ERR_UNSUPPORTED; + goto done; + } +#endif + + /* peer address type is only valid for directed */ + if ((props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) && + (cmd->peer_addr_type > BLE_HCI_ADV_PEER_ADDR_MAX)) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + + /* Check filter policy (valid only for undirected) */ + if (!(props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) && + cmd->filter_policy > BLE_HCI_ADV_FILT_MAX) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + + if (!pri_phy_valid(cmd->pri_phy)) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + + /* check secondary phy only if not using legacy PDUs */ + if (!(props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) && + !sec_phy_valid(cmd->sec_phy)) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + + if (cmd->sid > 0x0f) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + + if (cmd->scan_req_notif > 0x01) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + + rc = BLE_ERR_SUCCESS; + + if (cmd->tx_power == 127) { + /* no preference */ + advsm->adv_txpwr = MYNEWT_VAL(BLE_LL_TX_PWR_DBM); + } else { + advsm->adv_txpwr = ble_phy_txpower_round(cmd->tx_power); + } + + /* we can always store as those are validated and used only when needed */ + advsm->peer_addr_type = cmd->peer_addr_type; + memcpy(advsm->peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN); + advsm->own_addr_type = cmd->own_addr_type; + advsm->adv_filter_policy = cmd->filter_policy; + advsm->adv_chanmask = cmd->pri_chan_map; + advsm->adv_itvl_min = adv_itvl_min; + advsm->adv_itvl_max = adv_itvl_max; + advsm->pri_phy = cmd->pri_phy; + advsm->sec_phy = cmd->sec_phy; + /* Update SID only */ + advsm->adi = (advsm->adi & 0x0fff) | ((cmd->sid << 12)); + + advsm->props = props; + + /* Set proper mbuf chain for aux data */ + if (props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + advsm->aux_data = NULL; + } else if (props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) { + advsm->aux_data = &advsm->scan_rsp_data; + } else { + advsm->aux_data = &advsm->adv_data; + } + + if (cmd->scan_req_notif) { + ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_SCAN_REQ_NOTIF); + } else { + ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_SCAN_REQ_NOTIF); + } + + ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_CONFIGURED); + +done: + /* Update TX power */ + rsp->tx_power = rc ? 0 : advsm->adv_txpwr; + + *rsplen = sizeof(*rsp); + return rc; +} + +int +ble_ll_adv_ext_set_adv_data(const uint8_t *cmdbuf, uint8_t cmdlen) +{ + const struct ble_hci_le_set_ext_adv_data_cp *cmd = (const void *) cmdbuf; + + if (cmdlen < sizeof(*cmd )) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (cmd->adv_data_len > BLE_HCI_MAX_EXT_ADV_DATA_LEN || + cmd->adv_data_len > cmdlen - sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* TODO fragment preference ignored for now */ + + return ble_ll_adv_set_adv_data(cmd->adv_data, cmd->adv_data_len, + cmd->adv_handle, cmd->operation); +} + +int +ble_ll_adv_ext_set_scan_rsp(const uint8_t *cmdbuf, uint8_t cmdlen) +{ + const struct ble_hci_le_set_ext_scan_rsp_data_cp *cmd = (const void *) cmdbuf; + + if (cmdlen < sizeof(*cmd )) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (cmd->scan_rsp_len > BLE_HCI_MAX_EXT_ADV_DATA_LEN || + cmd->scan_rsp_len > cmdlen - sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* TODO fragment preference ignored for now */ + + return ble_ll_adv_set_scan_rsp_data(cmd->scan_rsp, cmd->scan_rsp_len, + cmd->adv_handle, cmd->operation); +} + +/** + * HCI LE extended advertising enable command + * + * @param cmd Pointer to command data + * @param len Command data length + * + * @return int BLE error code + */ +int +ble_ll_adv_ext_set_enable(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_set_ext_adv_enable_cp *cmd = (const void *) cmdbuf; + struct ble_ll_adv_sm *advsm; + int i, j, rc; + + if (len < sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* check if length is correct */ + if (len != 2 + (cmd->num_sets * sizeof(cmd->sets[0]))) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (cmd->num_sets > BLE_ADV_INSTANCES) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (cmd->num_sets == 0) { + if (cmd->enable) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* disable all instances */ + for (i = 0; i < BLE_ADV_INSTANCES; i++) { + ble_ll_adv_set_enable(i, 0, 0, 0); + } + + return BLE_ERR_SUCCESS; + } + + /* validate instances */ + for (i = 0; i < cmd->num_sets; i++) { + /* validate duplicated sets */ + for (j = i + 1; j < cmd->num_sets; j++) { + if (cmd->sets[i].adv_handle == cmd->sets[j].adv_handle) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + } + + advsm = ble_ll_adv_sm_find_configured(cmd->sets[i].adv_handle); + if (!advsm) { + return BLE_ERR_UNK_ADV_INDENT; + } + + if (cmd->enable) { + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { + if (cmd->sets[i].duration == 0 || + le16toh(cmd->sets[i].duration) > 128) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + } + } + } + + for (i = 0; i < cmd->num_sets; i++) { + rc = ble_ll_adv_set_enable(cmd->sets[i].adv_handle, cmd->enable, + le16toh(cmd->sets[i].duration), + cmd->sets[i].max_events); + if (rc) { + return rc; + } + } + + return BLE_ERR_SUCCESS; +} + +int +ble_ll_adv_set_random_addr(const uint8_t *addr, uint8_t instance) +{ + struct ble_ll_adv_sm *advsm; + + advsm = ble_ll_adv_sm_find_configured(instance); + if (!advsm) { + return BLE_ERR_UNK_ADV_INDENT; + } + + /* + * Reject if connectable advertising is on + * Core Spec Vol. 2 Part E 7.8.52 + */ + if (advsm->adv_enabled && + (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE)) { + return BLE_ERR_CMD_DISALLOWED; + } + + memcpy(advsm->adv_random_addr, addr, BLE_DEV_ADDR_LEN); + return BLE_ERR_SUCCESS; +} + +int +ble_ll_adv_hci_set_random_addr(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_set_adv_set_rnd_addr_cp *cmd = (const void *) cmdbuf; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + return ble_ll_adv_set_random_addr(cmd->addr, cmd->adv_handle); +} + +/** + * HCI LE extended advertising remove command + * + * @return int BLE error code + */ +int +ble_ll_adv_remove(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_remove_adv_set_cp *cmd = (const void *) cmdbuf; + struct ble_ll_adv_sm *advsm; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + advsm = ble_ll_adv_sm_find_configured(cmd->adv_handle); + if (!advsm) { + return BLE_ERR_UNK_ADV_INDENT; + } + + if (advsm->adv_enabled) { + return BLE_ERR_CMD_DISALLOWED; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + if (advsm->periodic_adv_enabled) { + return BLE_ERR_CMD_DISALLOWED; + } + + if (advsm->periodic_adv_data) { + os_mbuf_free_chain(advsm->periodic_adv_data); + } +#endif + + if (advsm->adv_data) { + os_mbuf_free_chain(advsm->adv_data); + } + if (advsm->scan_rsp_data) { + os_mbuf_free_chain(advsm->scan_rsp_data); + } + + ble_ll_adv_sm_init(advsm); + + return BLE_ERR_SUCCESS; +} + +/** + * HCI LE extended advertising clear command + * + * @return int BLE error code + */ +int +ble_ll_adv_clear_all(void) +{ + int i; + + for (i = 0; i < BLE_ADV_INSTANCES; i++) { + if (g_ble_ll_adv_sm[i].adv_enabled) { + return BLE_ERR_CMD_DISALLOWED; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + if (g_ble_ll_adv_sm[i].periodic_adv_enabled) { + return BLE_ERR_CMD_DISALLOWED; + } +#endif + } + + ble_ll_adv_reset(); + + return BLE_ERR_SUCCESS; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) +static uint16_t +ble_ll_adv_sync_get_pdu_len(uint16_t data_len, uint16_t *data_offset, + uint16_t props) +{ + uint16_t rem_data_len = data_len - *data_offset; + uint8_t hdr_len = BLE_LL_EXT_ADV_HDR_LEN; + uint8_t ext_hdr = 0; + + /* TxPower if configured + * Note: TxPower shall not be present in chain PDU for SYNC + */ + if (*data_offset == 0 && + (props & BLE_HCI_LE_SET_PERIODIC_ADV_PROP_INC_TX_PWR)) { + ext_hdr |= (1 << BLE_LL_EXT_ADV_TX_POWER_BIT); + hdr_len += BLE_LL_EXT_ADV_TX_POWER_SIZE; + } + + /* if we have any fields in ext header we need to add flags, note that Aux + * PTR is handled later and it will account for flags if needed + * + * This could be handled inside TxPower but lets keep code consistent with + * how Aux calculate works and this also make it easier to add more fields + * into flags if needed in future + */ + if (ext_hdr) { + hdr_len += BLE_LL_EXT_ADV_FLAGS_SIZE; + } + + /* AdvData always */ + data_len = min(BLE_LL_MAX_PAYLOAD_LEN - hdr_len, rem_data_len); + + /* AuxPtr if there are more AdvData remaining that we can fit here */ + if (rem_data_len > data_len) { + /* adjust for flags that needs to be added if AuxPtr is only field + * in Extended Header + */ + if (!ext_hdr) { + hdr_len += BLE_LL_EXT_ADV_FLAGS_SIZE; + data_len -= BLE_LL_EXT_ADV_FLAGS_SIZE; + } + + hdr_len += BLE_LL_EXT_ADV_AUX_PTR_SIZE; + data_len -= BLE_LL_EXT_ADV_AUX_PTR_SIZE; + + /* PDU payload should be full if chained */ + BLE_LL_ASSERT(hdr_len + data_len == BLE_LL_MAX_PAYLOAD_LEN); + } + + *data_offset += data_len; + + return hdr_len + data_len; +} + +static bool +ble_ll_adv_periodic_check_data_itvl(uint16_t payload_len, uint16_t props, + uint16_t itvl, uint8_t phy) +{ + uint32_t max_usecs = 0; + uint32_t itvl_usecs; + uint16_t offset = 0; + uint16_t pdu_len; + + while (offset < payload_len) { + pdu_len = ble_ll_adv_sync_get_pdu_len(payload_len, &offset, props); + + max_usecs += ble_ll_pdu_tx_time_get(pdu_len, phy); + max_usecs += ble_ll_usecs_to_ticks_round_up(BLE_LL_MAFS + + MYNEWT_VAL(BLE_LL_SCHED_AUX_CHAIN_MAFS_DELAY)); + } + + itvl_usecs = (uint32_t)itvl * BLE_LL_ADV_PERIODIC_ITVL; + + return max_usecs < itvl_usecs; +} + +int +ble_ll_adv_periodic_set_param(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_set_periodic_adv_params_cp *cmd = (const void *) cmdbuf; + struct ble_ll_adv_sm *advsm; + uint16_t adv_itvl_min; + uint16_t adv_itvl_max; + uint16_t props; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + adv_itvl_min = le16toh(cmd->min_itvl); + adv_itvl_max = le16toh(cmd->max_itvl); + props = le16toh(cmd->props); + + advsm = ble_ll_adv_sm_find_configured(cmd->adv_handle); + if (!advsm) { + return BLE_ERR_UNK_ADV_INDENT; + } + + /* If the advertising set identified by the Advertising_Handle specified + * scannable, connectable, legacy, or anonymous advertising, the Controller + * shall return the error code Invalid HCI Command Parameters (0x12). + */ + if (advsm->props & (BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV | + BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE | + BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE | + BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* If the Host issues this command when periodic advertising is enabled for + * the specified advertising set, the Controller shall return the error code + * Command Disallowed (0x0C). + */ + if (advsm->periodic_adv_enabled) { + return BLE_ERR_CMD_DISALLOWED; + } + + /* validate intervals */ + if ((adv_itvl_min < 0x0006) || (adv_itvl_max < 0x006) || + (adv_itvl_min > adv_itvl_max)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* validate properties */ + if (props & ~BLE_HCI_LE_SET_PERIODIC_ADV_PROP_MASK) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* If the advertising set already contains periodic advertising data and the + * length of the data is greater than the maximum that the Controller can + * transmit within a periodic advertising interval of + * Periodic_Advertising_Interval_Max, the Controller shall return the error + * code Packet Too Long (0x45). + */ + if (!ble_ll_adv_periodic_check_data_itvl(SYNC_DATA_LEN(advsm), props, + adv_itvl_max, advsm->sec_phy)) { + return BLE_ERR_PACKET_TOO_LONG; + } + + advsm->periodic_adv_itvl_min = adv_itvl_min; + advsm->periodic_adv_itvl_max = adv_itvl_max; + advsm->periodic_adv_props = props; + + ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_PERIODIC_CONFIGURED); + + return BLE_ERR_SUCCESS; +} + +int +ble_ll_adv_periodic_set_data(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_set_periodic_adv_data_cp *cmd = (const void *) cmdbuf; + struct ble_ll_adv_sm *advsm; + uint16_t payload_total_len; + bool new_data = false; + + if (len < sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (cmd->adv_data_len > BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN || + cmd->adv_data_len != len - sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + advsm = ble_ll_adv_sm_find_configured(cmd->adv_handle); + if (!advsm) { + return BLE_ERR_UNK_ADV_INDENT; + } + + if (!(advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_CONFIGURED)) { + return BLE_ERR_CMD_DISALLOWED; + } + + switch (cmd->operation) { + case BLE_HCI_LE_SET_DATA_OPER_LAST: + case BLE_HCI_LE_SET_DATA_OPER_INT: + if (!(advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_DATA_INCOMPLETE)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (!advsm->periodic_adv_data || !cmd->adv_data_len) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (advsm->periodic_adv_enabled) { + return BLE_ERR_CMD_DISALLOWED; + } + break; + case BLE_HCI_LE_SET_DATA_OPER_FIRST: + if (advsm->periodic_adv_enabled) { + return BLE_ERR_CMD_DISALLOWED; + } + + if (!cmd->adv_data_len) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + new_data = true; + break; + case BLE_HCI_LE_SET_DATA_OPER_COMPLETE: + new_data = true; + break; + default: + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + payload_total_len = cmd->adv_data_len; + if (!new_data) { + payload_total_len += SYNC_DATA_LEN(advsm); + } + + /* If the combined length of the data is greater than the maximum that the + * Controller can transmit within the current periodic advertising interval + * (if periodic advertising is currently enabled) or the + * Periodic_Advertising_Interval_Max for the advertising set (if currently + * disabled), all the data shall be discarded and the Controller shall + * return the error code Packet Too Long (0x45). + */ + if (!ble_ll_adv_periodic_check_data_itvl(payload_total_len, + advsm->periodic_adv_props, + advsm->periodic_adv_itvl_max, + advsm->sec_phy)) { + return BLE_ERR_PACKET_TOO_LONG; + } + + if (advsm->periodic_adv_active) { + ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_PERIODIC_NEW_DATA); + + ble_ll_adv_update_data_mbuf(&advsm->periodic_new_data, true, + BLE_ADV_DATA_MAX_LEN, + cmd->adv_data, cmd->adv_data_len); + if (!advsm->periodic_new_data) { + return BLE_ERR_MEM_CAPACITY; + } + + ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_PERIODIC_NEW_DATA); + } else { + ble_ll_adv_update_data_mbuf(&advsm->periodic_adv_data, new_data, + BLE_ADV_DATA_MAX_LEN, cmd->adv_data, + cmd->adv_data_len); + if (!advsm->periodic_adv_data) { + return BLE_ERR_MEM_CAPACITY; + } + } + + /* set/clear incomplete data flag only on success */ + switch (cmd->operation) { + case BLE_HCI_LE_SET_DATA_OPER_LAST: + case BLE_HCI_LE_SET_DATA_OPER_COMPLETE: + ble_ll_adv_flags_clear(advsm, + BLE_LL_ADV_SM_FLAG_PERIODIC_DATA_INCOMPLETE); + break; + case BLE_HCI_LE_SET_DATA_OPER_INT: + case BLE_HCI_LE_SET_DATA_OPER_FIRST: + default: + ble_ll_adv_flags_set(advsm, + BLE_LL_ADV_SM_FLAG_PERIODIC_DATA_INCOMPLETE); + break; + } + + return BLE_ERR_SUCCESS; +} + +int +ble_ll_adv_periodic_enable(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_set_periodic_adv_enable_cp *cmd = (const void *)cmdbuf; + struct ble_ll_adv_sm *advsm; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + advsm = ble_ll_adv_sm_find_configured(cmd->adv_handle); + if (!advsm) { + return BLE_ERR_UNK_ADV_INDENT; + } + + if (cmd->enable) { + if (advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_DATA_INCOMPLETE) { + return BLE_ERR_CMD_DISALLOWED; + } + + /* If Enable is set to 0x01 and the length of the periodic advertising + * data is greater than the maximum that the Controller can transmit + * within the chosen periodicadvertising interval, the Controller shall + * return the error code Packet Too Long (0x45). + */ + if (!ble_ll_adv_periodic_check_data_itvl(SYNC_DATA_LEN(advsm), + advsm->periodic_adv_props, + advsm->periodic_adv_itvl_max, + advsm->sec_phy)) { + return BLE_ERR_PACKET_TOO_LONG; + } + + /* If the advertising set is not currently enabled (see the + * LE_Set_Extended_Advertising_Enable command), the periodic advertising + * is not started until the advertising set is enabled. + */ + if (advsm->adv_enabled && !advsm->periodic_adv_active) { + /* Start the periodic advertising state machine */ + ble_ll_adv_sm_start_periodic(advsm); + } + } else { + /* Stop the periodic advertising state machine */ + ble_ll_adv_sm_stop_periodic(advsm); + } + + advsm->periodic_adv_enabled = cmd->enable; + + return BLE_ERR_SUCCESS; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) +static int +ble_ll_adv_periodic_send_sync_ind(struct ble_ll_adv_sm *advsm, + struct ble_ll_conn_sm *connsm, + uint16_t service_data) +{ + struct os_mbuf *om; + uint8_t *sync_ind; + + om = os_msys_get_pkthdr(BLE_LL_CTRL_MAX_PDU_LEN, + sizeof(struct ble_mbuf_hdr)); + if (!om) { + return BLE_ERR_MEM_CAPACITY; + } + + om->om_data[0] = BLE_LL_CTRL_PERIODIC_SYNC_IND; + + sync_ind = om->om_data + 1; + + /* ID (service_data), already in LE order */ + memcpy(sync_ind, &service_data, sizeof(service_data)); + + /* fill in syncinfo */ + ble_ll_adv_put_syncinfo(advsm, connsm, sync_ind + 20, sync_ind + 2); + + /* lastPaEventCounter */ + put_le16(sync_ind + 22, advsm->periodic_event_cntr_last_sent); + + /* SID, AType, SCA */ + sync_ind[24] = (advsm->adi >> 12); + sync_ind[24] |= !!(advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) << 4 ; + sync_ind[24] |= MYNEWT_VAL(BLE_LL_MASTER_SCA) << 5; + + /* PHY */ + sync_ind[25] = (0x01 << (advsm->sec_phy - 1)); + + /* AdvA */ + memcpy(sync_ind + 26, advsm->adva, BLE_DEV_ADDR_LEN); + + /* syncConnEventCount */ + put_le16(sync_ind + 32, connsm->event_cntr); + + ble_ll_conn_enqueue_pkt(connsm, om, BLE_LL_LLID_CTRL, + BLE_LL_CTRL_PERIODIC_SYNC_IND_LEN + 1); + + return BLE_ERR_SUCCESS; +} + +int +ble_ll_adv_periodic_set_info_transfer(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_le_periodic_adv_set_info_transfer_cp *cmd = (const void *)cmdbuf; + struct ble_hci_le_periodic_adv_set_info_transfer_rp *rsp = (void *) rspbuf; + struct ble_ll_conn_sm *connsm; + struct ble_ll_adv_sm *advsm; + uint16_t handle; + int rc; + + if (len != sizeof(*cmd)) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + + advsm = ble_ll_adv_sm_find_configured(cmd->adv_handle); + if (!advsm) { + rc = BLE_ERR_UNK_ADV_INDENT; + goto done; + } + + if (!advsm->periodic_adv_active) { + rc = BLE_ERR_CMD_DISALLOWED; + goto done; + } + + handle = le16toh(cmd->conn_handle); + if (handle > 0xeff) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + + connsm = ble_ll_conn_find_active_conn(handle); + if (!connsm) { + rc = BLE_ERR_UNK_CONN_ID; + goto done; + } + + /* TODO should not need to shift + * byte 3 (0 byte is conn_feature) , bit 1 + * + * Allow initiate LL procedure only if remote supports it. + */ + if (!(connsm->remote_features[2] & (BLE_LL_FEAT_SYNC_TRANS_RECV >> (8 * 3)))) { + rc = BLE_ERR_UNSUPP_REM_FEATURE; + goto done; + } + + rc = ble_ll_adv_periodic_send_sync_ind(advsm, connsm, cmd->service_data); + done: + rsp->conn_handle = cmd->conn_handle; + *rsplen = sizeof(*rsp); + return rc; +} +#endif +#endif +#endif + +/** + * Says whether the specified address is already connected or not. + * @param [in] addr The peer address. + * @param [in] addr_type Public address (0) or random address (1). + * @return Return 1 if already connected, 0 otherwise. + */ +static int +ble_ll_adv_already_connected(const uint8_t* addr, uint8_t addr_type) +{ + struct ble_ll_conn_sm *connsm; + + /* extracted from ble_ll_conn_slave_start function */ + SLIST_FOREACH(connsm, &g_ble_ll_conn_active_list, act_sle) { + if (!memcmp(&connsm->peer_addr, addr, BLE_DEV_ADDR_LEN)) { + if (addr_type == BLE_ADDR_RANDOM) { + if (connsm->peer_addr_type & 1) { + return 1; + } + } else { + if ((connsm->peer_addr_type & 1) == 0) { + return 1; + } + } + } + } + + return 0; +} + +/** + * Called when the LL receives a scan request or connection request + * + * Context: Called from interrupt context. + * + * @param rxbuf + * + * @return -1: request not for us or is a connect request. + * 0: request (scan) is for us and we successfully went from rx to tx. + * > 0: PHY error attempting to go from rx to tx. + */ +static int +ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu) +{ + int rc; + int resolved; + uint8_t chk_wl; + uint8_t txadd; + uint8_t peer_addr_type; + uint8_t *rxbuf; + uint8_t *adva; + uint8_t *peer; + struct ble_mbuf_hdr *ble_hdr; + struct ble_ll_adv_sm *advsm; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + struct aux_conn_rsp_data rsp_data; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + struct ble_ll_resolv_entry *rl; +#endif + + /* See if adva in the request (scan or connect) matches what we sent */ + advsm = g_ble_ll_cur_adv_sm; + rxbuf = rxpdu->om_data; + adva = rxbuf + BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN; + if (memcmp(advsm->adva, adva, BLE_DEV_ADDR_LEN)) { + return -1; + } + + /* Set device match bit if we are whitelisting */ + if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) { + chk_wl = advsm->adv_filter_policy & 1; + } else { + chk_wl = advsm->adv_filter_policy & 2; + } + + /* Get the peer address type */ + if (rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK) { + txadd = BLE_ADDR_RANDOM; + } else { + txadd = BLE_ADDR_PUBLIC; + } + + ble_hdr = BLE_MBUF_HDR_PTR(rxpdu); + peer = rxbuf + BLE_LL_PDU_HDR_LEN; + peer_addr_type = txadd; + resolved = 0; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + rl = NULL; + if (ble_ll_resolv_enabled()) { + if (ble_ll_is_rpa(peer, txadd)) { + advsm->adv_rpa_index = ble_hw_resolv_list_match(); + if (advsm->adv_rpa_index >= 0) { + ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_RESOLVED; + rl = &g_ble_ll_resolv_list[advsm->adv_rpa_index]; + if (chk_wl) { + peer = rl->rl_identity_addr; + peer_addr_type = rl->rl_addr_type; + resolved = 1; + } + } else { + if (chk_wl) { + return -1; + } + } + } else { + /* Verify privacy mode */ + rl = ble_ll_resolv_list_find(peer, peer_addr_type); + if (rl && (rl->rl_priv_mode == BLE_HCI_PRIVACY_NETWORK) && + rl->rl_has_peer) { + return -1; + } + } + } +#endif + + /* Set device match bit if we are whitelisting */ + if (chk_wl && !ble_ll_whitelist_match(peer, peer_addr_type, resolved)) { + return -1; + } + + /* + * We set the device match bit to tell the upper layer that we will + * accept the request + */ + ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_DEVMATCH; + + /* Setup to transmit the scan response if appropriate */ + rc = -1; + + if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) { + /* PHY used for scan requests shall be the same as the PHY used for the + * PDU that they reply to so no need to change PHY mode. + */ + ble_phy_set_txend_cb(ble_ll_adv_tx_done, advsm); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (advsm->flags & BLE_LL_ADV_SM_FLAG_SCAN_REQ_NOTIF) { + ble_ll_hci_ev_send_scan_req_recv(advsm->adv_instance, peer, + peer_addr_type); + } + + /* + * We need to store current rxed packet header temporarily so AuxPtr + * can be calculated (if necessary) relative to AUX_SCAN_RSP instead of + * AUX_ADV_IND. + */ + + advsm->rx_ble_hdr = ble_hdr; + rc = ble_phy_tx(ble_ll_adv_scan_rsp_pdu_make, advsm, + BLE_PHY_TRANSITION_NONE); + advsm->rx_ble_hdr = NULL; +#else + rc = ble_phy_tx(ble_ll_adv_scan_rsp_legacy_pdu_make, advsm, + BLE_PHY_TRANSITION_NONE); +#endif + + if (!rc) { + ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_SCAN_RSP_TXD; + STATS_INC(ble_ll_stats, scan_rsp_txg); + } + } else if (pdu_type == BLE_ADV_PDU_TYPE_AUX_CONNECT_REQ) { + /* See if the device is already connected */ + if (ble_ll_adv_already_connected(peer, peer_addr_type)) { + return -1; + } + + /* + * Only accept connect requests from the desired address if we + * are doing directed advertising + */ + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { + if (memcmp(advsm->initiator_addr, peer, BLE_DEV_ADDR_LEN)) { + return -1; + } + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + return -1; + } + + /* use remote address used over the air */ + rsp_data.advsm = advsm; + rsp_data.peer = rxbuf + BLE_LL_PDU_HDR_LEN; + rsp_data.rxadd = rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK; + + ble_phy_set_txend_cb(ble_ll_adv_tx_done, advsm); + rc = ble_phy_tx(ble_ll_adv_aux_conn_rsp_pdu_make, &rsp_data, + BLE_PHY_TRANSITION_NONE); + if (!rc) { + ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD); + STATS_INC(ble_ll_stats, aux_conn_rsp_tx); + } +#endif + } + + return rc; +} + +/** + * Called when a connect request has been received. + * + * Context: Link Layer + * + * @param rxbuf + * @param flags + * + * @return 0: no connection started. 1: connection started + */ +static int +ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, struct ble_mbuf_hdr *hdr, + struct ble_ll_adv_sm *advsm) +{ + int valid; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + uint8_t resolved; +#endif + uint8_t addr_type; + uint8_t *inita; + uint8_t *ident_addr; + + /* Don't create connection if AUX_CONNECT_RSP was not send */ + if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)) { + if (!(advsm->flags & BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD)) { + return 0; + } + } + + /* Check filter policy. */ + valid = 0; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + resolved = BLE_MBUF_HDR_RESOLVED(hdr); +#endif + inita = rxbuf + BLE_LL_PDU_HDR_LEN; + if (hdr->rxinfo.flags & BLE_MBUF_HDR_F_DEVMATCH) { + + valid = 1; + if (rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK) { + addr_type = BLE_ADDR_RANDOM; + } else { + addr_type = BLE_ADDR_PUBLIC; + } + + /* + * Only accept connect requests from the desired address if we + * are doing directed advertising + */ + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { + ident_addr = inita; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + if (resolved) { + ident_addr = g_ble_ll_resolv_list[advsm->adv_rpa_index].rl_identity_addr; + addr_type = g_ble_ll_resolv_list[advsm->adv_rpa_index].rl_addr_type; + } +#endif + if ((addr_type != advsm->peer_addr_type) || + memcmp(advsm->peer_addr, ident_addr, BLE_DEV_ADDR_LEN)) { + valid = 0; + } + } + } + + if (valid) { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + if (resolved) { + /* Retain the resolvable private address that we received. */ + memcpy(advsm->adv_rpa, inita, BLE_DEV_ADDR_LEN); + + /* Update resolving list with current peer RPA */ + ble_ll_resolv_set_peer_rpa(advsm->adv_rpa_index, inita); + + /* + * Overwrite received inita with identity address since that + * is used from now on. + */ + memcpy(inita, + g_ble_ll_resolv_list[advsm->adv_rpa_index].rl_identity_addr, + BLE_DEV_ADDR_LEN); + + /* Peer address type is an identity address */ + addr_type = g_ble_ll_resolv_list[advsm->adv_rpa_index].rl_addr_type; + addr_type += 2; + } +#endif + + /* Try to start slave connection. If successful, stop advertising */ + valid = ble_ll_conn_slave_start(rxbuf, addr_type, hdr, + !(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)); + if (valid) { + /* stop advertising only if not transmitting connection response */ + if (!(advsm->flags & BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD)) { + ble_ll_adv_sm_stop(advsm); + } + } + } + + return valid; +} + +/** + * Called on phy rx pdu end when in advertising state. + * + * There are only two pdu types we care about in this state: scan requests + * and connection requests. When we receive a scan request we must determine if + * we need to send a scan response and that needs to be acted on within T_IFS. + * + * When we receive a connection request, we need to determine if we will allow + * this device to start a connection with us. However, no immediate response is + * sent so we handle this at the link layer task. + * + * Context: Interrupt + * + * @param pdu_type Type of pdu received. + * @param rxpdu Pointer to received PDU + * + * @return int + * < 0: Disable the phy after reception. + * == 0: Do not disable the PHY + * > 0: Do not disable PHY as that has already been done. + */ +int +ble_ll_adv_rx_isr_end(uint8_t pdu_type, struct os_mbuf *rxpdu, int crcok) +{ + int rc; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + struct ble_mbuf_hdr *rxhdr; +#endif + + rc = -1; + if (rxpdu == NULL) { + ble_ll_adv_tx_done(g_ble_ll_cur_adv_sm); + } else { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + rxhdr = BLE_MBUF_HDR_PTR(rxpdu); + rxhdr->rxinfo.user_data = g_ble_ll_cur_adv_sm; + if (ble_ll_adv_active_chanset_is_sec(g_ble_ll_cur_adv_sm)) { + rxhdr->rxinfo.flags |= BLE_MBUF_HDR_F_EXT_ADV_SEC; + } else { + assert(ble_ll_adv_active_chanset_is_pri(g_ble_ll_cur_adv_sm)); + } +#endif + if (crcok) { + if ((pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) || + (pdu_type == BLE_ADV_PDU_TYPE_CONNECT_IND)) { + /* Process request */ + rc = ble_ll_adv_rx_req(pdu_type, rxpdu); + } + } + + if (rc) { + /* We no longer have a current state machine */ + g_ble_ll_cur_adv_sm = NULL; + } + } + + if (rc) { + ble_ll_state_set(BLE_LL_STATE_STANDBY); + } + + return rc; +} + +/** + * Process a received packet at the link layer task when in the advertising + * state + * + * Context: Link Layer + * + * + * @param ptype + * @param rxbuf + * @param hdr + * + * @return int + */ +void +ble_ll_adv_rx_pkt_in(uint8_t ptype, uint8_t *rxbuf, struct ble_mbuf_hdr *hdr) +{ + int adv_event_over; + struct ble_ll_adv_sm *advsm; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + advsm = (struct ble_ll_adv_sm *)hdr->rxinfo.user_data; +#else + advsm = &g_ble_ll_adv_sm[0]; +#endif + + /* + * It is possible that advertising was stopped and a packet plcaed on the + * LL receive packet queue. In this case, just ignore the received packet + * as the advertising state machine is no longer "valid" + */ + if (!advsm->adv_enabled) { + return; + } + + /* + * If we have received a scan request and we are transmitting a response + * or we have received a valid connect request, dont "end" the advertising + * event. In the case of a connect request we will stop advertising. In + * the case of the scan response transmission we will get a transmit + * end callback. + */ + adv_event_over = 1; + if (BLE_MBUF_HDR_CRC_OK(hdr)) { + if (ptype == BLE_ADV_PDU_TYPE_CONNECT_IND) { + if (ble_ll_adv_conn_req_rxd(rxbuf, hdr, advsm)) { + adv_event_over = 0; + } + } else { + if ((ptype == BLE_ADV_PDU_TYPE_SCAN_REQ) && + (hdr->rxinfo.flags & BLE_MBUF_HDR_F_SCAN_RSP_TXD)) { + adv_event_over = 0; + } + } + } + + if (adv_event_over) { + ble_ll_adv_make_done(advsm, hdr); + } +} + +/** + * Called when a receive PDU has started and we are advertising. + * + * Context: interrupt + * + * @param pdu_type + * @param rxpdu + * + * @return int + * < 0: A frame we dont want to receive. + * = 0: Continue to receive frame. Dont go from rx to tx + * > 0: Continue to receive frame and go from rx to tx when done + */ +int +ble_ll_adv_rx_isr_start(uint8_t pdu_type) +{ + int rc; + struct ble_ll_adv_sm *advsm; + + /* Assume we will abort the frame */ + rc = -1; + + /* If we get a scan request we must tell the phy to go from rx to tx */ + advsm = g_ble_ll_cur_adv_sm; + if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) { + /* Only accept scan requests if we are indirect adv or scan adv */ + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) { + rc = 1; + } + } else { + /* Only accept connect requests if connectable advertising event */ + if (pdu_type == BLE_ADV_PDU_TYPE_CONNECT_IND) { + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { + /* Need transition to TX if extended adv */ + rc = !(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY); + } + } + } + + /* + * If we abort the frame, we need to post the LL task to check if the + * advertising event is over. + */ + if (rc < 0) { + ble_ll_adv_tx_done(advsm); + } + + return rc; +} + +static void +ble_ll_adv_drop_event(struct ble_ll_adv_sm *advsm) +{ + STATS_INC(ble_ll_stats, adv_drop_event); + + ble_ll_sched_rmv_elem(&advsm->adv_sch); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + ble_ll_sched_rmv_elem(&advsm->aux[0].sch); + ble_ll_sched_rmv_elem(&advsm->aux[1].sch); + + ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev); + advsm->aux_active = 0; +#endif + + advsm->adv_chan = ble_ll_adv_final_chan(advsm); + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); +} + +static void +ble_ll_adv_reschedule_event(struct ble_ll_adv_sm *advsm) +{ + int rc; + uint32_t start_time; + uint32_t max_delay_ticks; + + assert(advsm->adv_enabled); + + if (!advsm->adv_sch.enqueued) { + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { + max_delay_ticks = 0; + } else { + max_delay_ticks = + os_cputime_usecs_to_ticks(BLE_LL_ADV_DELAY_MS_MAX * 1000); + } + + rc = ble_ll_sched_adv_reschedule(&advsm->adv_sch, &start_time, + max_delay_ticks); + if (rc) { + ble_ll_adv_drop_event(advsm); + return; + } + + start_time += g_ble_ll_sched_offset_ticks; + advsm->adv_event_start_time = start_time; + advsm->adv_pdu_start_time = start_time; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) && + !advsm->aux_active) { + ble_ll_adv_aux_schedule(advsm); + } +#endif +} + +/** + * Called when an advertising event is over. + * + * Context: Link Layer task. + * + * @param arg Pointer to advertising state machine. + */ +static void +ble_ll_adv_done(struct ble_ll_adv_sm *advsm) + +{ + int rc; + int resched_pdu; + uint8_t mask; + uint8_t final_adv_chan; + int32_t delta_t; + uint32_t itvl; + uint32_t tick_itvl; + uint32_t start_time; + + assert(advsm->adv_enabled); + + ble_ll_rfmgmt_release(); + + ble_ll_adv_update_adv_scan_rsp_data(advsm); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { + /* stop advertising this was due to transmitting connection response */ + if (advsm->flags & BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD) { + ble_ll_adv_sm_stop(advsm); + return; + } + } +#endif + + /* Remove the element from the schedule if it is still there. */ + ble_ll_sched_rmv_elem(&advsm->adv_sch); + + ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); + + /* + * Check if we have ended our advertising event. If our last advertising + * packet was sent on the last channel, it means we are done with this + * event. + */ + final_adv_chan = ble_ll_adv_final_chan(advsm); + + if (advsm->adv_chan == final_adv_chan) { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (advsm->events_max) { + advsm->events++; + } +#endif + + ble_ll_scan_chk_resume(); + + /* This event is over. Set adv channel to first one */ + advsm->adv_chan = ble_ll_adv_first_chan(advsm); + + /* + * Calculate start time of next advertising event. NOTE: we do not + * add the random advDelay as the scheduling code will do that. + */ + itvl = advsm->adv_itvl_usecs; + tick_itvl = os_cputime_usecs_to_ticks(itvl); + advsm->adv_event_start_time += tick_itvl; + advsm->adv_pdu_start_time = advsm->adv_event_start_time; + + /* + * The scheduled time better be in the future! If it is not, we will + * just keep advancing until we the time is in the future + */ + start_time = advsm->adv_pdu_start_time - g_ble_ll_sched_offset_ticks; + + delta_t = (int32_t)(start_time - os_cputime_get32()); + if (delta_t < 0) { + /* + * NOTE: we just the same interval that we calculated earlier. + * No real need to keep recalculating a new interval. + */ + while (delta_t < 0) { + advsm->adv_event_start_time += tick_itvl; + advsm->adv_pdu_start_time = advsm->adv_event_start_time; + delta_t += (int32_t)tick_itvl; + } + } + resched_pdu = 0; + } else { + /* + * Move to next advertising channel. If not in the mask, just + * increment by 1. We can do this because we already checked if we + * just transmitted on the last advertising channel + */ + ++advsm->adv_chan; + mask = 1 << (advsm->adv_chan - BLE_PHY_ADV_CHAN_START); + if ((mask & advsm->adv_chanmask) == 0) { + ++advsm->adv_chan; + } + + /* + * We will transmit right away. Set next pdu start time to now + * plus a xcvr start delay just so we dont count late adv starts + */ + advsm->adv_pdu_start_time = os_cputime_get32() + + g_ble_ll_sched_offset_ticks; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + /* If we're past aux (unlikely, but can happen), just drop an event */ + if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) && + advsm->aux_active && + advsm->adv_pdu_start_time > AUX_CURRENT(advsm)->start_time) { + ble_ll_adv_drop_event(advsm); + return; + } +#endif + + resched_pdu = 1; + } + + /* check if advertising timed out */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (advsm->duration && + advsm->adv_pdu_start_time >= advsm->adv_end_time) { + /* Legacy PDUs need to be stop here. + * For ext adv it will be stopped when AUX is done (unless it was + * dropped so check if AUX is active here as well). + */ + if ((advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) || + !advsm->aux_active) { + ble_ll_adv_sm_stop_timeout(advsm); + } + + return; + } +#else + if ((advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) && + (advsm->adv_pdu_start_time >= advsm->adv_end_time)) { + ble_ll_adv_sm_stop_timeout(advsm); + return; + } +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (advsm->events_max && (advsm->events >= advsm->events_max)) { + /* Legacy PDUs need to be stop here. + * For ext adv it will be stopped when AUX is done (unless it was + * dropped so check if AUX is active here as well). + */ + if ((advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) || + !advsm->aux_active) { + ble_ll_adv_sm_stop_limit_reached(advsm); + } + + return; + } +#endif + + /* We need to regenerate our RPA's if we have passed timeout */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + ble_ll_adv_chk_rpa_timeout(advsm); +#endif + + /* Schedule advertising transmit */ + ble_ll_adv_set_sched(advsm); + + if (!resched_pdu) { + ble_ll_adv_reschedule_event(advsm); + return; + } + + /* + * In the unlikely event we can't reschedule this, just post a done event + * and we will reschedule the next advertising PDU. + */ + rc = ble_ll_sched_adv_resched_pdu(&advsm->adv_sch); + if (rc) { + STATS_INC(ble_ll_stats, adv_resched_pdu_fail); + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); + } +} + +static void +ble_ll_adv_event_done(struct ble_npl_event *ev) +{ + ble_ll_adv_done(ble_npl_event_get_arg(ev)); +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +/** + * Called when auxiliary packet is txd on secondary channel + * + * Context: Link Layer task. + * + * @param ev + */ +static void +ble_ll_adv_sec_done(struct ble_ll_adv_sm *advsm) +{ + struct ble_ll_adv_aux *aux; + struct ble_ll_adv_aux *aux_next; + + assert(advsm->adv_enabled); + assert(advsm->aux_active); + + aux = AUX_CURRENT(advsm); + aux_next = AUX_NEXT(advsm); + + /* We don't need RF anymore */ + ble_ll_rfmgmt_release(); + + if (advsm->aux_not_scanned) { + ble_ll_sched_rmv_elem(&aux_next->sch); + } + + /* Remove anything else scheduled for secondary channel */ + ble_ll_sched_rmv_elem(&aux->sch); + ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev); + + /* Stop advertising due to transmitting connection response */ + if (advsm->flags & BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD) { + ble_ll_adv_sm_stop(advsm); + return; + } + + /* If we have next AUX scheduled, try to schedule another one */ + if (aux_next->sch.enqueued) { + advsm->aux_index ^= 1; + advsm->aux_first_pdu = 0; + ble_ll_adv_aux_schedule_next(advsm); + return; + } + + ble_ll_scan_chk_resume(); + + /* Check if advertising timed out */ + if (advsm->duration && (advsm->adv_pdu_start_time >= advsm->adv_end_time)) { + ble_ll_adv_sm_stop_timeout(advsm); + return; + } + + if (advsm->events_max && (advsm->events >= advsm->events_max)) { + ble_ll_adv_sm_stop_limit_reached(advsm); + return; + } + + advsm->aux_active = 0; + ble_ll_adv_update_adv_scan_rsp_data(advsm); + ble_ll_adv_reschedule_event(advsm); +} + +static void +ble_ll_adv_sec_event_done(struct ble_npl_event *ev) +{ + ble_ll_adv_sec_done(ble_npl_event_get_arg(ev)); +} +#endif + +static void +ble_ll_adv_make_done(struct ble_ll_adv_sm *advsm, struct ble_mbuf_hdr *hdr) +{ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (BLE_MBUF_HDR_EXT_ADV_SEC(hdr)) { + assert(!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)); + assert(ble_ll_adv_active_chanset_is_sec(advsm)); + ble_ll_adv_active_chanset_clear(advsm); + ble_ll_adv_sec_done(advsm); + } else { + assert(ble_ll_adv_active_chanset_is_pri(advsm)); + ble_ll_adv_active_chanset_clear(advsm); + ble_ll_adv_done(advsm); + } +#else + ble_ll_adv_active_chanset_clear(advsm); + ble_ll_adv_done(advsm); +#endif +} + +/** + * Checks if the controller can change the whitelist. If advertising is enabled + * and is using the whitelist the controller is not allowed to change the + * whitelist. + * + * @return int 0: not allowed to change whitelist; 1: change allowed. + */ +int +ble_ll_adv_can_chg_whitelist(void) +{ + struct ble_ll_adv_sm *advsm; + int rc; + int i; + + rc = 1; + for (i = 0; i < BLE_ADV_INSTANCES; ++i) { + advsm = &g_ble_ll_adv_sm[i]; + if (advsm->adv_enabled && + (advsm->adv_filter_policy != BLE_HCI_ADV_FILT_NONE)) { + rc = 0; + break; + } + } + + return rc; +} + +/** + * Sends the connection complete event when advertising a connection starts. + * + * @return uint8_t* Pointer to event buffer + */ +void +ble_ll_adv_send_conn_comp_ev(struct ble_ll_conn_sm *connsm, + struct ble_mbuf_hdr *rxhdr) +{ + uint8_t *evbuf; + struct ble_ll_adv_sm *advsm; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + advsm = (struct ble_ll_adv_sm *)rxhdr->rxinfo.user_data; +#else + advsm = &g_ble_ll_adv_sm[0]; +#endif + + evbuf = advsm->conn_comp_ev; + assert(evbuf != NULL); + advsm->conn_comp_ev = NULL; + + ble_ll_conn_comp_event_send(connsm, BLE_ERR_SUCCESS, evbuf, advsm); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) + ble_ll_hci_ev_le_csa(connsm); +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (ble_ll_hci_adv_mode_ext()) { + ble_ll_hci_ev_send_adv_set_terminated(0, advsm->adv_instance, + connsm->conn_handle, advsm->events); + } +#endif +} + +/** + * Returns the local resolvable private address currently being using by + * the advertiser + * + * @return uint8_t* + */ +uint8_t * +ble_ll_adv_get_local_rpa(struct ble_ll_adv_sm *advsm) +{ + uint8_t *rpa = NULL; + + if (advsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) { + if ((advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) && + ble_ll_is_rpa(advsm->adva, 1)) { + rpa = advsm->adva; + } + } + + return rpa; +} + +/** + * Returns the peer resolvable private address of last device connecting to us + * + * @return uint8_t* + */ +uint8_t * +ble_ll_adv_get_peer_rpa(struct ble_ll_adv_sm *advsm) +{ + /* XXX: should this go into IRK list or connection? */ + return advsm->adv_rpa; +} + +/** + * Called when the LL wait for response timer expires while in the advertising + * state. Disables the phy and + * + */ +void +ble_ll_adv_wfr_timer_exp(void) +{ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + g_ble_ll_cur_adv_sm->aux_not_scanned = 1; +#endif + + ble_phy_disable(); + ble_ll_adv_tx_done(g_ble_ll_cur_adv_sm); +} + +/** + * Reset the advertising state machine. + * + * Context: Link Layer task + * + */ +void +ble_ll_adv_reset(void) +{ + int i; + struct ble_ll_adv_sm *advsm; + + for (i = 0; i < BLE_ADV_INSTANCES; ++i) { + advsm = &g_ble_ll_adv_sm[i]; + + /* Stop advertising state machine */ + ble_ll_adv_sm_stop(advsm); + + /* clear any data present */ + os_mbuf_free_chain(advsm->adv_data); + os_mbuf_free_chain(advsm->scan_rsp_data); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + /* Stop periodic advertising state machine */ + ble_ll_adv_sm_stop_periodic(advsm); + + /* clear any periodic data present */ + os_mbuf_free_chain(advsm->periodic_adv_data); +#endif + + /* re-initialize the advertiser state machine */ + ble_ll_adv_sm_init(advsm); + } +} + +/* Called to determine if advertising is enabled. + */ +uint8_t +ble_ll_adv_enabled(void) +{ + int i; + + for (i = 0; i < BLE_ADV_INSTANCES; i++) { + if (g_ble_ll_adv_sm[i].adv_enabled) { + return 1; + } + } + + return 0; +} + +static void +ble_ll_adv_sm_init(struct ble_ll_adv_sm *advsm) +{ + memset(advsm, 0, sizeof(struct ble_ll_adv_sm)); + + advsm->adv_itvl_min = BLE_HCI_ADV_ITVL_DEF; + advsm->adv_itvl_max = BLE_HCI_ADV_ITVL_DEF; + advsm->adv_chanmask = BLE_HCI_ADV_CHANMASK_DEF; + + /* Initialize advertising tx done event */ + ble_npl_event_init(&advsm->adv_txdone_ev, ble_ll_adv_event_done, advsm); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + ble_npl_event_init(&advsm->adv_sec_txdone_ev, ble_ll_adv_sec_event_done, advsm); +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + ble_npl_event_init(&advsm->adv_periodic_txdone_ev, + ble_ll_adv_periodic_event_done, advsm); +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + /* Initialize aux schedulers */ + advsm->aux_active = 0; + advsm->aux[0].sch.cb_arg = advsm; + advsm->aux[0].sch.sched_cb = ble_ll_adv_secondary_tx_start_cb; + advsm->aux[0].sch.sched_type = BLE_LL_SCHED_TYPE_ADV; + advsm->aux[1].sch.cb_arg = advsm; + advsm->aux[1].sch.sched_cb = ble_ll_adv_secondary_tx_start_cb; + advsm->aux[1].sch.sched_type = BLE_LL_SCHED_TYPE_ADV; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + /* Initialize sync schedulers */ + advsm->periodic_sync_active = 0; + advsm->periodic_sync[0].sch.cb_arg = advsm; + advsm->periodic_sync[0].sch.sched_cb = ble_ll_adv_sync_tx_start_cb; + advsm->periodic_sync[0].sch.sched_type = BLE_LL_SCHED_TYPE_PERIODIC; + advsm->periodic_sync[1].sch.cb_arg = advsm; + advsm->periodic_sync[1].sch.sched_cb = ble_ll_adv_sync_tx_start_cb; + advsm->periodic_sync[1].sch.sched_type = BLE_LL_SCHED_TYPE_PERIODIC; +#endif +#endif + + /* Configure instances to be legacy on start */ + advsm->props |= BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE; + advsm->props |= BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY; +} + +/** + * Initialize the advertising functionality of a BLE device. This should + * be called once on initialization + */ +void +ble_ll_adv_init(void) +{ + int i; + + /* Set default advertising parameters */ + for (i = 0; i < BLE_ADV_INSTANCES; ++i) { + ble_ll_adv_sm_init(&g_ble_ll_adv_sm[i]); + } +} + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn.c new file mode 100644 index 000000000..b3788de1d --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn.c @@ -0,0 +1,4279 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef ESP_PLATFORM + +#include +#include +#include +#include +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/porting/nimble/include/os/os_cputime.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/include/nimble/nimble_opt.h" +#include "nimble/nimble/include/nimble/hci_common.h" +#include "nimble/nimble/include/nimble/ble_hci_trans.h" + +#if defined(ARDUINO_ARCH_NRF5) && defined(NRF51) +#include "nimble/nimble/drivers/nrf51/include/ble/xcvr.h" +#elif defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) +#include "nimble/nimble/drivers/nrf52/include/ble/xcvr.h" +#endif + +#include "../include/controller/ble_ll.h" +#include "../include/controller/ble_ll_hci.h" +#include "../include/controller/ble_ll_scan.h" +#include "../include/controller/ble_ll_whitelist.h" +#include "../include/controller/ble_ll_sched.h" +#include "../include/controller/ble_ll_ctrl.h" +#include "../include/controller/ble_ll_resolv.h" +#include "../include/controller/ble_ll_adv.h" +#include "../include/controller/ble_ll_trace.h" +#include "../include/controller/ble_ll_rfmgmt.h" +#include "../include/controller/ble_phy.h" +#include "../include/controller/ble_hw.h" +#include "../include/controller/ble_ll_utils.h" +#include "ble_ll_conn_priv.h" + +#if (BLETEST_THROUGHPUT_TEST == 1) +extern void bletest_completed_pkt(uint16_t handle); +#endif + +/* XXX TODO + * 1) I think if we are initiating and we already have a connection with + * a device that we will still try and connect to it. Fix this. + * -> This is true. There are a couple things to do + * i) When a connection create is issued, if we already are connected + * deny it. BLE ERROR = 0x0B (ACL connection exists). + * ii) If we receive an advertisement while initiating and want to send + * a connect request to the device, make sure we dont have it. + * iii) I think I need to do something like this: I am initiating and + * advertising. Suppose the device I want to connect to sends me a connect + * request because I am advertising? What happens to connection? Deal + * with this! + * + * 2) Make sure we check incoming data packets for size and all that. You + * know, supported octets and all that. For both rx and tx. + * + * 3) Make sure we are setting the schedule end time properly for both slave + * and master. We should just set this to the end of the connection event. + * We might want to guarantee a IFS time as well since the next event needs + * to be scheduled prior to the start of the event to account for the time it + * takes to get a frame ready (which is pretty much the IFS time). + * + * 4) looks like the current code will allow the 1st packet in a + * connection to extend past the end of the allocated connection end + * time. That is not good. Need to deal with that. Need to extend connection + * end time. + * + * 6) Use error code 0x3E correctly! Connection failed to establish. If you + * read the LE connection complete event, it says that if the connection + * fails to be established that the connection complete event gets sent to + * the host that issued the create connection. Need to resolve this. + * + * 7) How does peer address get set if we are using whitelist? Look at filter + * policy and make sure you are doing this correctly. + * + * 8) Right now I use a fixed definition for required slots. CHange this. + * + * 10) See what connection state machine elements are purely master and + * purely slave. We can make a union of them. + * + * 11) Not sure I am dealing with the connection terminate timeout perfectly. + * I may extend a connection event too long although if it is always in terms + * of connection events I am probably fine. Checking at end that the next + * connection event will occur past terminate timeould would be fine. + * + * 12) When a slave receives a data packet in a connection it has to send a + * response. Well, it should. If this packet will overrun the next scheduled + * event, what should we do? Transmit anyway? Not transmit? For now, we just + * transmit. + * + * 32kHz crystal + * 1) When scheduling, I need to make sure I have time between + * this one and the next. Should I deal with this in the sched. Or + * is this basically accounted for given a slot? I really just need to + * make sure everything is over N ticks before the next sched start! + * Just add to end time? + * + * 2) I think one way to handle the problem of losing up to a microsecond + * every time we call ble_ll_conn_next_event in a loop is to do everything by + * keeping track of last anchor point. Would need last anchor usecs too. I guess + * we could also keep last anchor usecs as a uint32 or something and when we + * do the next event keep track of the residual using a different ticks to + * usecs calculation. Not sure. + */ + +/* + * XXX: How should we deal with a late connection event? We need to determine + * what we want to do under the following cases: + * 1) The current connection event has not ended but a schedule item starts + */ + +/* This is a dummy structure we use for the empty PDU */ +struct ble_ll_empty_pdu +{ + struct os_mbuf om; + struct os_mbuf_pkthdr pkt_hdr; + struct ble_mbuf_hdr ble_hdr; +}; + +/* We cannot have more than 254 connections given our current implementation */ +#if (MYNEWT_VAL(BLE_MAX_CONNECTIONS) >= 255) + #error "Maximum # of connections is 254" +#endif + +/* Global connection complete event. Used when initiating */ +uint8_t *g_ble_ll_conn_comp_ev; + +/* Global LL connection parameters */ +struct ble_ll_conn_global_params g_ble_ll_conn_params; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) +/* Global default sync transfer params */ +struct ble_ll_conn_sync_transfer_params g_ble_ll_conn_sync_transfer_params; +#endif + +/* Pointer to connection state machine we are trying to create */ +struct ble_ll_conn_sm *g_ble_ll_conn_create_sm; + +/* Pointer to current connection */ +struct ble_ll_conn_sm *g_ble_ll_conn_cur_sm; + +/* Connection state machine array */ +struct ble_ll_conn_sm g_ble_ll_conn_sm[MYNEWT_VAL(BLE_MAX_CONNECTIONS)]; + +/* List of active connections */ +struct ble_ll_conn_active_list g_ble_ll_conn_active_list; + +/* List of free connections */ +struct ble_ll_conn_free_list g_ble_ll_conn_free_list; + +STATS_SECT_START(ble_ll_conn_stats) + STATS_SECT_ENTRY(cant_set_sched) + STATS_SECT_ENTRY(conn_ev_late) + STATS_SECT_ENTRY(wfr_expirations) + STATS_SECT_ENTRY(handle_not_found) + STATS_SECT_ENTRY(no_conn_sm) + STATS_SECT_ENTRY(no_free_conn_sm) + STATS_SECT_ENTRY(rx_data_pdu_no_conn) + STATS_SECT_ENTRY(rx_data_pdu_bad_aa) + STATS_SECT_ENTRY(slave_rxd_bad_conn_req_params) + STATS_SECT_ENTRY(slave_ce_failures) + STATS_SECT_ENTRY(data_pdu_rx_dup) + STATS_SECT_ENTRY(data_pdu_txg) + STATS_SECT_ENTRY(data_pdu_txf) + STATS_SECT_ENTRY(conn_req_txd) + STATS_SECT_ENTRY(l2cap_enqueued) + STATS_SECT_ENTRY(rx_ctrl_pdus) + STATS_SECT_ENTRY(rx_l2cap_pdus) + STATS_SECT_ENTRY(rx_l2cap_bytes) + STATS_SECT_ENTRY(rx_malformed_ctrl_pdus) + STATS_SECT_ENTRY(rx_bad_llid) + STATS_SECT_ENTRY(tx_ctrl_pdus) + STATS_SECT_ENTRY(tx_ctrl_bytes) + STATS_SECT_ENTRY(tx_l2cap_pdus) + STATS_SECT_ENTRY(tx_l2cap_bytes) + STATS_SECT_ENTRY(tx_empty_pdus) + STATS_SECT_ENTRY(mic_failures) + STATS_SECT_ENTRY(sched_start_in_idle) + STATS_SECT_ENTRY(sched_end_in_idle) + STATS_SECT_ENTRY(conn_event_while_tmo) +STATS_SECT_END +STATS_SECT_DECL(ble_ll_conn_stats) ble_ll_conn_stats; + +STATS_NAME_START(ble_ll_conn_stats) + STATS_NAME(ble_ll_conn_stats, cant_set_sched) + STATS_NAME(ble_ll_conn_stats, conn_ev_late) + STATS_NAME(ble_ll_conn_stats, wfr_expirations) + STATS_NAME(ble_ll_conn_stats, handle_not_found) + STATS_NAME(ble_ll_conn_stats, no_conn_sm) + STATS_NAME(ble_ll_conn_stats, no_free_conn_sm) + STATS_NAME(ble_ll_conn_stats, rx_data_pdu_no_conn) + STATS_NAME(ble_ll_conn_stats, rx_data_pdu_bad_aa) + STATS_NAME(ble_ll_conn_stats, slave_rxd_bad_conn_req_params) + STATS_NAME(ble_ll_conn_stats, slave_ce_failures) + STATS_NAME(ble_ll_conn_stats, data_pdu_rx_dup) + STATS_NAME(ble_ll_conn_stats, data_pdu_txg) + STATS_NAME(ble_ll_conn_stats, data_pdu_txf) + STATS_NAME(ble_ll_conn_stats, conn_req_txd) + STATS_NAME(ble_ll_conn_stats, l2cap_enqueued) + STATS_NAME(ble_ll_conn_stats, rx_ctrl_pdus) + STATS_NAME(ble_ll_conn_stats, rx_l2cap_pdus) + STATS_NAME(ble_ll_conn_stats, rx_l2cap_bytes) + STATS_NAME(ble_ll_conn_stats, rx_malformed_ctrl_pdus) + STATS_NAME(ble_ll_conn_stats, rx_bad_llid) + STATS_NAME(ble_ll_conn_stats, tx_ctrl_pdus) + STATS_NAME(ble_ll_conn_stats, tx_ctrl_bytes) + STATS_NAME(ble_ll_conn_stats, tx_l2cap_pdus) + STATS_NAME(ble_ll_conn_stats, tx_l2cap_bytes) + STATS_NAME(ble_ll_conn_stats, tx_empty_pdus) + STATS_NAME(ble_ll_conn_stats, mic_failures) + STATS_NAME(ble_ll_conn_stats, sched_start_in_idle) + STATS_NAME(ble_ll_conn_stats, sched_end_in_idle) + STATS_NAME(ble_ll_conn_stats, conn_event_while_tmo) +STATS_NAME_END(ble_ll_conn_stats) + +static void ble_ll_conn_event_end(struct ble_npl_event *ev); + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +/** + * Checks to see if we should start a PHY update procedure + * + * If current phy is not one of the preferred we need to start control + * procedure. + * + * XXX: we could also decide to change the PHY if RSSI is really good + * and we are currently at 1Mbps or lower data rate and we could use + * a higher data rate. + * + * @param connsm + * @return 0: success; -1: no phy update procedure started + */ +int +ble_ll_conn_chk_phy_upd_start(struct ble_ll_conn_sm *csm) +{ + int rc; + + /* If no host preferences or */ + if (((csm->phy_data.host_pref_tx_phys_mask == 0) && + (csm->phy_data.host_pref_rx_phys_mask == 0)) || + ((csm->phy_data.host_pref_tx_phys_mask & CONN_CUR_TX_PHY_MASK(csm)) && + (csm->phy_data.host_pref_rx_phys_mask & CONN_CUR_RX_PHY_MASK(csm)))) { + rc = -1; + } else { + csm->phy_data.req_pref_tx_phys_mask = csm->phy_data.host_pref_tx_phys_mask; + csm->phy_data.req_pref_rx_phys_mask = csm->phy_data.host_pref_rx_phys_mask; + ble_ll_ctrl_proc_start(csm, BLE_LL_CTRL_PROC_PHY_UPDATE); + rc = 0; + } + + return rc; +} +#endif + +static void +ble_ll_conn_calc_itvl_ticks(struct ble_ll_conn_sm *connsm) +{ + uint32_t ticks; + uint32_t usecs; + + /* + * Precalculate the number of ticks and remaining microseconds for + * the connection interval + */ + usecs = connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS; + ticks = os_cputime_usecs_to_ticks(usecs); + connsm->conn_itvl_usecs = (uint8_t)(usecs - + os_cputime_ticks_to_usecs(ticks)); + if (connsm->conn_itvl_usecs == 31) { + connsm->conn_itvl_usecs = 0; + ++ticks; + } + connsm->conn_itvl_ticks = ticks; +} + +/** + * Get the event buffer allocated to send the connection complete event + * when we are initiating. + * + * @return uint8_t* + */ +static uint8_t * +ble_ll_init_get_conn_comp_ev(void) +{ + uint8_t *evbuf; + + evbuf = g_ble_ll_conn_comp_ev; + BLE_LL_ASSERT(evbuf != NULL); + g_ble_ll_conn_comp_ev = NULL; + + return evbuf; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) +/** + * Called to determine if the received PDU is an empty PDU or not. + */ +static int +ble_ll_conn_is_empty_pdu(uint8_t *rxbuf) +{ + int rc; + uint8_t llid; + + llid = rxbuf[0] & BLE_LL_DATA_HDR_LLID_MASK; + if ((llid == BLE_LL_LLID_DATA_FRAG) && (rxbuf[1] == 0)) { + rc = 1; + } else { + rc = 0; + } + return rc; +} +#endif + +/** + * Called to return the currently running connection state machine end time. + * Always called when interrupts are disabled. + * + * @return int 0: s1 is not least recently used. 1: s1 is least recently used + */ +int +ble_ll_conn_is_lru(struct ble_ll_conn_sm *s1, struct ble_ll_conn_sm *s2) +{ + int rc; + + /* Set time that we last serviced the schedule */ + if ((int32_t)(s1->last_scheduled - s2->last_scheduled) < 0) { + rc = 1; + } else { + rc = 0; + } + + return rc; +} + +/** + * Called to return the currently running connection state machine end time. + * Always called when interrupts are disabled. + * + * @return uint32_t + */ +uint32_t +ble_ll_conn_get_ce_end_time(void) +{ + uint32_t ce_end_time; + + if (g_ble_ll_conn_cur_sm) { + ce_end_time = g_ble_ll_conn_cur_sm->ce_end_time; + } else { + ce_end_time = os_cputime_get32(); + } + return ce_end_time; +} + +/** + * Called when connection state machine needs to halt. This function will: + * -> Disable the PHY, which will prevent any transmit/receive interrupts. + * -> Disable the wait for response timer, if running. + * -> Remove the connection state machine from the scheduler. + * -> Sets the Link Layer state to standby. + * -> Sets the current state machine to NULL. + * + * NOTE: the ordering of these function calls is important! We have to stop + * the PHY and remove the schedule item before we can set the state to + * standby and set the current state machine pointer to NULL. + */ +static void +ble_ll_conn_halt(void) +{ + ble_phy_disable(); + ble_ll_state_set(BLE_LL_STATE_STANDBY); + g_ble_ll_conn_cur_sm = NULL; +} + +/** + * Called when the current connection state machine is no longer being used. + */ +static void +ble_ll_conn_current_sm_over(struct ble_ll_conn_sm *connsm) +{ + + ble_ll_conn_halt(); + + /* + * NOTE: the connection state machine may be NULL if we are calling + * this when we are ending the connection. In that case, there is no + * need to post to the LL the connection event end event + */ + if (connsm) { + ble_ll_event_send(&connsm->conn_ev_end); + } +} + +/** + * Given a handle, find an active connection matching the handle + * + * @param handle + * + * @return struct ble_ll_conn_sm* + */ +struct ble_ll_conn_sm * +ble_ll_conn_find_active_conn(uint16_t handle) +{ + struct ble_ll_conn_sm *connsm; + + connsm = NULL; + if ((handle != 0) && (handle <= MYNEWT_VAL(BLE_MAX_CONNECTIONS))) { + connsm = &g_ble_ll_conn_sm[handle - 1]; + if (connsm->conn_state == BLE_LL_CONN_STATE_IDLE) { + connsm = NULL; + } + } + return connsm; +} + +/** + * Get a connection state machine. + */ +struct ble_ll_conn_sm * +ble_ll_conn_sm_get(void) +{ + struct ble_ll_conn_sm *connsm; + + connsm = STAILQ_FIRST(&g_ble_ll_conn_free_list); + if (connsm) { + STAILQ_REMOVE_HEAD(&g_ble_ll_conn_free_list, free_stqe); + } else { + STATS_INC(ble_ll_conn_stats, no_free_conn_sm); + } + + return connsm; +} + +static uint8_t +ble_ll_conn_calc_dci_csa1(struct ble_ll_conn_sm *conn) +{ + uint8_t curchan; + uint8_t remap_index; + uint8_t bitpos; + + /* Get next unmapped channel */ + curchan = conn->last_unmapped_chan + conn->hop_inc; + if (curchan > BLE_PHY_NUM_DATA_CHANS) { + curchan -= BLE_PHY_NUM_DATA_CHANS; + } + + /* Save unmapped channel */ + conn->last_unmapped_chan = curchan; + + /* Is this a valid channel? */ + bitpos = 1 << (curchan & 0x07); + if (conn->chanmap[curchan >> 3] & bitpos) { + return curchan; + } + + /* Calculate remap index */ + remap_index = curchan % conn->num_used_chans; + + return ble_ll_utils_remapped_channel(remap_index, conn->chanmap); +} + +/** + * Determine data channel index to be used for the upcoming/current + * connection event + * + * @param conn + * @param latency Used only for CSA #1 + * + * @return uint8_t + */ +uint8_t +ble_ll_conn_calc_dci(struct ble_ll_conn_sm *conn, uint16_t latency) +{ + uint8_t index; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) + if (CONN_F_CSA2_SUPP(conn)) { + return ble_ll_utils_calc_dci_csa2(conn->event_cntr, conn->channel_id, + conn->num_used_chans, conn->chanmap); + } +#endif + + index = conn->data_chan_index; + + while (latency > 0) { + index = ble_ll_conn_calc_dci_csa1(conn); + latency--; + } + + return index; +} + +/** + * Called when we are in the connection state and the wait for response timer + * fires off. + * + * Context: Interrupt + */ +void +ble_ll_conn_wfr_timer_exp(void) +{ + struct ble_ll_conn_sm *connsm; + + connsm = g_ble_ll_conn_cur_sm; + ble_ll_conn_current_sm_over(connsm); + STATS_INC(ble_ll_conn_stats, wfr_expirations); +} + +void +ble_ll_conn_reset_pending_aux_conn_rsp(void) +{ +#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + return; +#endif + struct ble_ll_conn_sm *connsm; + + connsm = g_ble_ll_conn_create_sm; + if (!connsm) { + return; + } + + if (CONN_F_AUX_CONN_REQ(connsm)) { + STATS_INC(ble_ll_stats, aux_conn_rsp_err); + CONN_F_CONN_REQ_TXD(connsm) = 0; + CONN_F_AUX_CONN_REQ(connsm) = 0; + ble_ll_sched_rmv_elem(&connsm->conn_sch); + return; + } + + return; +} + +bool +ble_ll_conn_init_pending_aux_conn_rsp(void) +{ +#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + return false; +#endif + struct ble_ll_conn_sm *connsm; + + connsm = g_ble_ll_conn_create_sm; + if (!connsm) { + return false; + } + + return CONN_F_AUX_CONN_REQ(connsm); +} + +void +ble_ll_conn_init_wfr_timer_exp(void) +{ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + struct ble_ll_conn_sm *connsm; + + connsm = g_ble_ll_conn_create_sm; + if (!connsm) { + return; + } + + ble_ll_conn_reset_pending_aux_conn_rsp(); + connsm->inita_identity_used = 0; + + ble_ll_scan_interrupted(connsm->scansm); + +#endif +} +/** + * Callback for slave when it transmits a data pdu and the connection event + * ends after the transmission. + * + * Context: Interrupt + * + * @param sch + * + */ +static void +ble_ll_conn_wait_txend(void *arg) +{ + struct ble_ll_conn_sm *connsm; + + connsm = (struct ble_ll_conn_sm *)arg; + ble_ll_conn_current_sm_over(connsm); +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) +static void +ble_ll_conn_start_rx_encrypt(void *arg) +{ + struct ble_ll_conn_sm *connsm; + + connsm = (struct ble_ll_conn_sm *)arg; + CONN_F_ENCRYPTED(connsm) = 1; + ble_phy_encrypt_enable(connsm->enc_data.rx_pkt_cntr, + connsm->enc_data.iv, + connsm->enc_data.enc_block.cipher_text, + !CONN_IS_MASTER(connsm)); +} + +static void +ble_ll_conn_start_rx_unencrypt(void *arg) +{ + struct ble_ll_conn_sm *connsm; + + connsm = (struct ble_ll_conn_sm *)arg; + CONN_F_ENCRYPTED(connsm) = 0; + ble_phy_encrypt_disable(); +} + +static void +ble_ll_conn_txend_encrypt(void *arg) +{ + struct ble_ll_conn_sm *connsm; + + connsm = (struct ble_ll_conn_sm *)arg; + CONN_F_ENCRYPTED(connsm) = 1; + ble_ll_conn_current_sm_over(connsm); +} + +static void +ble_ll_conn_rxend_unencrypt(void *arg) +{ + struct ble_ll_conn_sm *connsm; + + connsm = (struct ble_ll_conn_sm *)arg; + CONN_F_ENCRYPTED(connsm) = 0; + ble_ll_conn_current_sm_over(connsm); +} + +static void +ble_ll_conn_continue_rx_encrypt(void *arg) +{ + struct ble_ll_conn_sm *connsm; + + connsm = (struct ble_ll_conn_sm *)arg; + ble_phy_encrypt_set_pkt_cntr(connsm->enc_data.rx_pkt_cntr, + !CONN_IS_MASTER(connsm)); +} +#endif + +/** + * Returns the cputime of the next scheduled item on the scheduler list or + * when the current connection will start its next interval (whichever is + * earlier). This API is called when determining at what time we should end + * the current connection event. The current connection event must end before + * the next scheduled item. However, the current connection itself is not + * in the scheduler list! Thus, we need to calculate the time at which the + * next connection will start (the schedule start time; not the anchor point) + * and not overrun it. + * + * Context: Interrupt + * + * @param connsm + * + * @return uint32_t + */ +static uint32_t +ble_ll_conn_get_next_sched_time(struct ble_ll_conn_sm *connsm) +{ +#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING) + uint32_t ce_end; + ce_end = connsm->ce_end_time; +#else + uint32_t ce_end; + uint32_t next_sched_time; + + /* Calculate time at which next connection event will start */ + /* NOTE: We dont care if this time is tick short. */ + ce_end = connsm->anchor_point + connsm->conn_itvl_ticks - + g_ble_ll_sched_offset_ticks; + if ((connsm->anchor_point_usecs + connsm->conn_itvl_usecs) >= 31) { + ++ce_end; + } + + if (ble_ll_sched_next_time(&next_sched_time)) { + if (CPUTIME_LT(next_sched_time, ce_end)) { + ce_end = next_sched_time; + } + } +#endif + + return ce_end; +} + +/** + * Called to check if certain connection state machine flags have been + * set. + * + * @param connsm + */ +static void +ble_ll_conn_chk_csm_flags(struct ble_ll_conn_sm *connsm) +{ + uint8_t update_status; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + if (connsm->csmflags.cfbit.send_ltk_req) { + /* + * Send Long term key request event to host. If masked, we need to + * send a REJECT_IND. + */ + if (ble_ll_hci_ev_ltk_req(connsm)) { + ble_ll_ctrl_reject_ind_send(connsm, BLE_LL_CTRL_ENC_REQ, + BLE_ERR_PINKEY_MISSING); + } + connsm->csmflags.cfbit.send_ltk_req = 0; + } +#endif + + /* + * There are two cases where this flag gets set: + * 1) A connection update procedure was started and the event counter + * has passed the instant. + * 2) We successfully sent the reject reason. + */ + if (connsm->csmflags.cfbit.host_expects_upd_event) { + update_status = BLE_ERR_SUCCESS; + if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_UPDATE)) { + ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_CONN_UPDATE); + } else { + if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ)) { + ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ); + update_status = connsm->reject_reason; + } + } + ble_ll_hci_ev_conn_update(connsm, update_status); + connsm->csmflags.cfbit.host_expects_upd_event = 0; + } + + /* Check if we need to send PHY update complete event */ +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + if (CONN_F_PHY_UPDATE_EVENT(connsm)) { + if (!ble_ll_hci_ev_phy_update(connsm, BLE_ERR_SUCCESS)) { + /* Sent event. Clear flag */ + CONN_F_PHY_UPDATE_EVENT(connsm) = 0; + } + } +#endif +} + +/** + * Called when we want to send a data channel pdu inside a connection event. + * + * Context: interrupt + * + * @param connsm + * + * @return int 0: success; otherwise failure to transmit + */ +static uint16_t +ble_ll_conn_adjust_pyld_len(struct ble_ll_conn_sm *connsm, uint16_t pyld_len) +{ + uint16_t phy_max_tx_octets; + uint16_t ret; + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + uint8_t phy_mode; + + if (connsm->phy_tx_transition) { + phy_mode = ble_ll_phy_to_phy_mode(connsm->phy_tx_transition, + connsm->phy_data.phy_options); + } else { + phy_mode = connsm->phy_data.tx_phy_mode; + } + + phy_max_tx_octets = ble_ll_pdu_max_tx_octets_get(connsm->eff_max_tx_time, + phy_mode); + +#else + phy_max_tx_octets = ble_ll_pdu_max_tx_octets_get(connsm->eff_max_tx_time, + BLE_PHY_MODE_1M); +#endif + + ret = pyld_len; + + if (ret > connsm->eff_max_tx_octets) { + ret = connsm->eff_max_tx_octets; + } + + if (ret > phy_max_tx_octets) { + ret = phy_max_tx_octets; + } + + return ret; +} + +static int +ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) +{ + int rc; + uint8_t md; + uint8_t hdr_byte; + uint8_t end_transition; + uint8_t cur_txlen; + uint8_t next_txlen; + uint8_t cur_offset; + uint16_t pktlen; + uint32_t next_event_time; + uint32_t ticks; + struct os_mbuf *m; + struct ble_mbuf_hdr *ble_hdr; + struct os_mbuf_pkthdr *pkthdr = NULL; + struct os_mbuf_pkthdr *nextpkthdr; + struct ble_ll_empty_pdu empty_pdu; + ble_phy_tx_end_func txend_func; + int tx_phy_mode; + uint8_t llid; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + int is_ctrl; + uint8_t opcode; +#endif + + /* For compiler warnings... */ + ble_hdr = NULL; + m = NULL; + md = 0; + hdr_byte = BLE_LL_LLID_DATA_FRAG; + + if (connsm->csmflags.cfbit.terminate_ind_rxd) { + /* We just received terminate indication. + * Just send empty packet as an ACK + */ + CONN_F_EMPTY_PDU_TXD(connsm) = 1; + goto conn_tx_pdu; + } + + /* + * We need to check if we are retrying a pdu or if there is a pdu on + * the transmit queue. + */ + pkthdr = STAILQ_FIRST(&connsm->conn_txq); + if (!connsm->cur_tx_pdu && !CONN_F_EMPTY_PDU_TXD(connsm) && !pkthdr) { + CONN_F_EMPTY_PDU_TXD(connsm) = 1; + goto conn_tx_pdu; + } + + /* + * If we dont have a pdu we have previously transmitted, take it off + * the connection transmit queue + */ + cur_offset = 0; + if (!connsm->cur_tx_pdu && !CONN_F_EMPTY_PDU_TXD(connsm)) { + /* Convert packet header to mbuf */ + m = OS_MBUF_PKTHDR_TO_MBUF(pkthdr); + nextpkthdr = STAILQ_NEXT(pkthdr, omp_next); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + /* + * If we are encrypting, we are only allowed to send certain + * kinds of LL control PDU's. If none is enqueued, send empty pdu! + */ + if (connsm->enc_data.enc_state > CONN_ENC_S_ENCRYPTED) { + if (!ble_ll_ctrl_enc_allowed_pdu_tx(pkthdr)) { + CONN_F_EMPTY_PDU_TXD(connsm) = 1; + goto conn_tx_pdu; + } + + /* + * We will allow a next packet if it itself is allowed or we are + * a slave and we are sending the START_ENC_RSP. The master has + * to wait to receive the START_ENC_RSP from the slave before + * packets can be let go. + */ + if (nextpkthdr && !ble_ll_ctrl_enc_allowed_pdu_tx(nextpkthdr) + && ((connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) || + !ble_ll_ctrl_is_start_enc_rsp(m))) { + nextpkthdr = NULL; + } + } +#endif + /* Take packet off queue*/ + STAILQ_REMOVE_HEAD(&connsm->conn_txq, omp_next); + ble_hdr = BLE_MBUF_HDR_PTR(m); + + /* + * We dequeued new packet for transmission. + * If this is a data PDU we need to calculate payload length we can send + * over current PHY. Effectively, this determines fragmentation of packet + * into PDUs. + * If this is a control PDU we send complete PDU as only data PDU can be + * fragmented. We assume that checks (i.e. if remote supports such PDU) + * were already performed before putting packet on queue. + */ + llid = ble_hdr->txinfo.hdr_byte & BLE_LL_DATA_HDR_LLID_MASK; + pktlen = pkthdr->omp_len; + if (llid == BLE_LL_LLID_CTRL) { + cur_txlen = pktlen; + } else { + cur_txlen = ble_ll_conn_adjust_pyld_len(connsm, pktlen); + } + ble_hdr->txinfo.pyld_len = cur_txlen; + + /* NOTE: header was set when first enqueued */ + hdr_byte = ble_hdr->txinfo.hdr_byte; + connsm->cur_tx_pdu = m; + } else { + nextpkthdr = pkthdr; + if (connsm->cur_tx_pdu) { + m = connsm->cur_tx_pdu; + ble_hdr = BLE_MBUF_HDR_PTR(m); + pktlen = OS_MBUF_PKTLEN(m); + cur_txlen = ble_hdr->txinfo.pyld_len; + cur_offset = ble_hdr->txinfo.offset; + if (cur_offset == 0) { + hdr_byte = ble_hdr->txinfo.hdr_byte & BLE_LL_DATA_HDR_LLID_MASK; + } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + if (connsm->enc_data.enc_state > CONN_ENC_S_ENCRYPTED) { + /* We will allow a next packet if it itself is allowed */ + pkthdr = OS_MBUF_PKTHDR(connsm->cur_tx_pdu); + if (nextpkthdr && !ble_ll_ctrl_enc_allowed_pdu_tx(nextpkthdr) + && ((connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) || + !ble_ll_ctrl_is_start_enc_rsp(connsm->cur_tx_pdu))) { + nextpkthdr = NULL; + } + } +#endif + } else { + /* Empty PDU here. NOTE: header byte gets set later */ + pktlen = 0; + cur_txlen = 0; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + if (connsm->enc_data.enc_state > CONN_ENC_S_ENCRYPTED) { + /* We will allow a next packet if it itself is allowed */ + if (nextpkthdr && !ble_ll_ctrl_enc_allowed_pdu_tx(nextpkthdr)) { + nextpkthdr = NULL; + } + } +#endif + } + } + + /* + * Set the more data data flag if we have more data to send and we + * have not been asked to terminate + */ + if (nextpkthdr || ((cur_offset + cur_txlen) < pktlen)) { + /* Get next event time */ + next_event_time = ble_ll_conn_get_next_sched_time(connsm); + + /* XXX: TODO: need to check this with phy update procedure. There are + limitations if we have started update */ + + /* + * Dont bother to set the MD bit if we cannot do the following: + * -> wait IFS, send the current frame. + * -> wait IFS, receive a maximum size frame. + * -> wait IFS, send the next frame. + * -> wait IFS, receive a maximum size frame. + * + * For slave: + * -> wait IFS, send current frame. + * -> wait IFS, receive maximum size frame. + * -> wait IFS, send next frame. + */ + if ((cur_offset + cur_txlen) < pktlen) { + next_txlen = pktlen - (cur_offset + cur_txlen); + } else { + if (nextpkthdr->omp_len > connsm->eff_max_tx_octets) { + next_txlen = connsm->eff_max_tx_octets; + } else { + next_txlen = nextpkthdr->omp_len; + } + } + + /* + * XXX: this calculation is based on using the current time + * and assuming the transmission will occur an IFS time from + * now. This is not the most accurate especially if we have + * received a frame and we are replying to it. + */ +#if BLE_LL_BT5_PHY_SUPPORTED + tx_phy_mode = connsm->phy_data.tx_phy_mode; +#else + tx_phy_mode = BLE_PHY_MODE_1M; +#endif + + ticks = (BLE_LL_IFS * 3) + connsm->eff_max_rx_time + + ble_ll_pdu_tx_time_get(next_txlen, tx_phy_mode) + + ble_ll_pdu_tx_time_get(cur_txlen, tx_phy_mode); + + if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + ticks += (BLE_LL_IFS + connsm->eff_max_rx_time); + } + + ticks = os_cputime_usecs_to_ticks(ticks); + if ((int32_t)((os_cputime_get32() + ticks) - next_event_time) < 0) { + md = 1; + } + } + + /* If we send an empty PDU we need to initialize the header */ +conn_tx_pdu: + if (CONN_F_EMPTY_PDU_TXD(connsm)) { + /* + * This looks strange, but we dont use the data pointer in the mbuf + * when we have an empty pdu. + */ + m = (struct os_mbuf *)&empty_pdu; + m->om_data = (uint8_t *)&empty_pdu; + m->om_data += BLE_MBUF_MEMBLOCK_OVERHEAD; + ble_hdr = &empty_pdu.ble_hdr; + ble_hdr->txinfo.flags = 0; + ble_hdr->txinfo.offset = 0; + ble_hdr->txinfo.pyld_len = 0; + } + + /* Set tx seqnum */ + if (connsm->tx_seqnum) { + hdr_byte |= BLE_LL_DATA_HDR_SN_MASK; + } + + /* If we have more data, set the bit */ + if (md) { + hdr_byte |= BLE_LL_DATA_HDR_MD_MASK; + } + + /* Set NESN (next expected sequence number) bit */ + if (connsm->next_exp_seqnum) { + hdr_byte |= BLE_LL_DATA_HDR_NESN_MASK; + } + + /* Set the header byte in the outgoing frame */ + ble_hdr->txinfo.hdr_byte = hdr_byte; + + /* + * If we are a slave, check to see if this transmission will end the + * connection event. We will end the connection event if we have + * received a valid frame with the more data bit set to 0 and we dont + * have more data. + * + * XXX: for a slave, we dont check to see if we can: + * -> wait IFS, rx frame from master (either big or small). + * -> wait IFS, send empty pdu or next pdu. + * + * We could do this. Now, we just keep going and hope that we dont + * overrun next scheduled item. + */ + if ((connsm->csmflags.cfbit.terminate_ind_rxd) || + ((connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) && (md == 0) && + (connsm->cons_rxd_bad_crc == 0) && + ((connsm->last_rxd_hdr_byte & BLE_LL_DATA_HDR_MD_MASK) == 0) && + !ble_ll_ctrl_is_terminate_ind(hdr_byte, m->om_data[0]))) { + /* We will end the connection event */ + end_transition = BLE_PHY_TRANSITION_NONE; + txend_func = ble_ll_conn_wait_txend; + } else { + /* Wait for a response here */ + end_transition = BLE_PHY_TRANSITION_TX_RX; + txend_func = NULL; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + llid = ble_hdr->txinfo.hdr_byte & BLE_LL_DATA_HDR_LLID_MASK; + if (llid == BLE_LL_LLID_CTRL) { + is_ctrl = 1; + opcode = m->om_data[0]; + } else { + is_ctrl = 0; + opcode = 0; + } + + if (is_ctrl && (opcode == BLE_LL_CTRL_START_ENC_RSP)) { + /* + * Both master and slave send the START_ENC_RSP encrypted and receive + * encrypted + */ + CONN_F_ENCRYPTED(connsm) = 1; + connsm->enc_data.tx_encrypted = 1; + ble_phy_encrypt_enable(connsm->enc_data.tx_pkt_cntr, + connsm->enc_data.iv, + connsm->enc_data.enc_block.cipher_text, + CONN_IS_MASTER(connsm)); + } else if (is_ctrl && (opcode == BLE_LL_CTRL_START_ENC_REQ)) { + /* + * Only the slave sends this and it gets sent unencrypted but + * we receive encrypted + */ + CONN_F_ENCRYPTED(connsm) = 0; + connsm->enc_data.enc_state = CONN_ENC_S_START_ENC_RSP_WAIT; + connsm->enc_data.tx_encrypted = 0; + ble_phy_encrypt_disable(); + if (txend_func == NULL) { + txend_func = ble_ll_conn_start_rx_encrypt; + } else { + txend_func = ble_ll_conn_txend_encrypt; + } + } else if (is_ctrl && (opcode == BLE_LL_CTRL_PAUSE_ENC_RSP)) { + /* + * The slave sends the PAUSE_ENC_RSP encrypted. The master sends + * it unencrypted (note that link was already set unencrypted). + */ + if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { + CONN_F_ENCRYPTED(connsm) = 1; + connsm->enc_data.tx_encrypted = 1; + ble_phy_encrypt_enable(connsm->enc_data.tx_pkt_cntr, + connsm->enc_data.iv, + connsm->enc_data.enc_block.cipher_text, + CONN_IS_MASTER(connsm)); + if (txend_func == NULL) { + txend_func = ble_ll_conn_start_rx_unencrypt; + } else { + txend_func = ble_ll_conn_rxend_unencrypt; + } + } else { + CONN_F_ENCRYPTED(connsm) = 0; + connsm->enc_data.enc_state = CONN_ENC_S_PAUSED; + connsm->enc_data.tx_encrypted = 0; + ble_phy_encrypt_disable(); + } + } else { + /* If encrypted set packet counter */ + if (CONN_F_ENCRYPTED(connsm)) { + connsm->enc_data.tx_encrypted = 1; + ble_phy_encrypt_set_pkt_cntr(connsm->enc_data.tx_pkt_cntr, + CONN_IS_MASTER(connsm)); + if (txend_func == NULL) { + txend_func = ble_ll_conn_continue_rx_encrypt; + } + } + } +#endif + + /* Set transmit end callback */ + ble_phy_set_txend_cb(txend_func, connsm); + rc = ble_phy_tx(ble_ll_tx_mbuf_pducb, m, end_transition); + if (!rc) { + /* Log transmit on connection state */ + cur_txlen = ble_hdr->txinfo.pyld_len; + ble_ll_trace_u32x2(BLE_LL_TRACE_ID_CONN_TX, cur_txlen, + ble_hdr->txinfo.offset); + + /* Set last transmitted MD bit */ + CONN_F_LAST_TXD_MD(connsm) = md; + + /* Increment packets transmitted */ + if (CONN_F_EMPTY_PDU_TXD(connsm)) { + if (connsm->csmflags.cfbit.terminate_ind_rxd) { + connsm->csmflags.cfbit.terminate_ind_rxd_acked = 1; + } + STATS_INC(ble_ll_conn_stats, tx_empty_pdus); + } else if ((hdr_byte & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_CTRL) { + STATS_INC(ble_ll_conn_stats, tx_ctrl_pdus); + STATS_INCN(ble_ll_conn_stats, tx_ctrl_bytes, cur_txlen); + } else { + STATS_INC(ble_ll_conn_stats, tx_l2cap_pdus); + STATS_INCN(ble_ll_conn_stats, tx_l2cap_bytes, cur_txlen); + } + } + return rc; +} + +/** + * Schedule callback for start of connection event. + * + * Context: Interrupt + * + * @param sch + * + * @return int 0: scheduled item is still running. 1: schedule item is done. + */ +static int +ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch) +{ + int rc; + uint32_t usecs; + uint32_t start; + struct ble_ll_conn_sm *connsm; + + /* XXX: note that we can extend end time here if we want. Look at this */ + + /* Set current connection state machine */ + connsm = (struct ble_ll_conn_sm *)sch->cb_arg; + g_ble_ll_conn_cur_sm = connsm; + BLE_LL_ASSERT(connsm); + if (connsm->conn_state == BLE_LL_CONN_STATE_IDLE) { + /* That should not happen. If it does it means connection + * is already closed + */ + STATS_INC(ble_ll_conn_stats, sched_start_in_idle); + BLE_LL_ASSERT(0); + ble_ll_conn_current_sm_over(connsm); + return BLE_LL_SCHED_STATE_DONE; + } + + /* Log connection event start */ + ble_ll_trace_u32(BLE_LL_TRACE_ID_CONN_EV_START, connsm->conn_handle); + + /* Disable whitelisting as connections do not use it */ + ble_ll_whitelist_disable(); + + /* Set LL state */ + ble_ll_state_set(BLE_LL_STATE_CONNECTION); + + /* Set channel */ + ble_phy_setchan(connsm->data_chan_index, connsm->access_addr, + connsm->crcinit); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + ble_phy_resolv_list_disable(); +#endif + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + ble_phy_mode_set(connsm->phy_data.tx_phy_mode, connsm->phy_data.rx_phy_mode); +#endif + + if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + /* Set start time of transmission */ + start = sch->start_time + g_ble_ll_sched_offset_ticks; + rc = ble_phy_tx_set_start_time(start, sch->remainder); + if (!rc) { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + if (CONN_F_ENCRYPTED(connsm)) { + ble_phy_encrypt_enable(connsm->enc_data.tx_pkt_cntr, + connsm->enc_data.iv, + connsm->enc_data.enc_block.cipher_text, + 1); + } else { + ble_phy_encrypt_disable(); + } +#endif + rc = ble_ll_conn_tx_pdu(connsm); + if (!rc) { + rc = BLE_LL_SCHED_STATE_RUNNING; + } else { + /* Inform LL task of connection event end */ + rc = BLE_LL_SCHED_STATE_DONE; + } + } else { + STATS_INC(ble_ll_conn_stats, conn_ev_late); + rc = BLE_LL_SCHED_STATE_DONE; + } + } else { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + if (CONN_F_ENCRYPTED(connsm)) { + ble_phy_encrypt_enable(connsm->enc_data.rx_pkt_cntr, + connsm->enc_data.iv, + connsm->enc_data.enc_block.cipher_text, + 1); + } else { + ble_phy_encrypt_disable(); + } +#endif + + /* XXX: what is this really for the slave? */ + start = sch->start_time + g_ble_ll_sched_offset_ticks; + rc = ble_phy_rx_set_start_time(start, sch->remainder); + if (rc) { + /* End the connection event as we have no more buffers */ + STATS_INC(ble_ll_conn_stats, slave_ce_failures); + rc = BLE_LL_SCHED_STATE_DONE; + } else { + /* + * Set flag that tells slave to set last anchor point if a packet + * has been received. + */ + connsm->csmflags.cfbit.slave_set_last_anchor = 1; + + /* + * Set the wait for response time. The anchor point is when we + * expect the master to start transmitting. Worst-case, we expect + * to hear a reply within the anchor point plus: + * -> current tx window size + * -> current window widening amount (includes +/- 16 usec jitter) + * -> Amount of time it takes to detect packet start. + * -> Some extra time (16 usec) to insure timing is OK + */ + + /* + * For the 32 kHz crystal, the amount of usecs we have to wait + * is not from the anchor point; we have to account for the time + * from when the receiver is enabled until the anchor point. The + * time we start before the anchor point is this: + * -> current window widening. + * -> up to one 32 kHz tick since we discard remainder. + * -> Up to one tick since the usecs to ticks calc can be off + * by up to one tick. + * NOTES: + * 1) the 61 we add is for the two ticks mentioned above. + * 2) The address rx time and jitter is accounted for in the + * phy function + */ + usecs = connsm->slave_cur_tx_win_usecs + 61 + + (2 * connsm->slave_cur_window_widening); + ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_RX, 0, usecs); + /* Set next wakeup time to connection event end time */ + rc = BLE_LL_SCHED_STATE_RUNNING; + } + } + + if (rc == BLE_LL_SCHED_STATE_DONE) { + ble_ll_event_send(&connsm->conn_ev_end); + ble_phy_disable(); + ble_ll_state_set(BLE_LL_STATE_STANDBY); + g_ble_ll_conn_cur_sm = NULL; + } + + /* Set time that we last serviced the schedule */ + connsm->last_scheduled = os_cputime_get32(); + return rc; +} + +/** + * Called to determine if the device is allowed to send the next pdu in the + * connection event. This will always return 'true' if we are a slave. If we + * are a master, we must be able to send the next fragment and get a minimum + * sized response from the slave. + * + * Context: Interrupt context (rx end isr). + * + * @param connsm + * @param begtime Time at which IFS before pdu transmission starts + * + * @return int 0: not allowed to send 1: allowed to send + */ +static int +ble_ll_conn_can_send_next_pdu(struct ble_ll_conn_sm *connsm, uint32_t begtime, + uint32_t add_usecs) +{ + int rc; + uint8_t rem_bytes; + uint32_t ticks; + uint32_t usecs; + uint32_t next_sched_time; + struct os_mbuf *txpdu; + struct os_mbuf_pkthdr *pkthdr; + struct ble_mbuf_hdr *txhdr; + uint32_t allowed_usecs; + int tx_phy_mode; + +#if BLE_LL_BT5_PHY_SUPPORTED + tx_phy_mode = connsm->phy_data.tx_phy_mode; +#else + tx_phy_mode = BLE_PHY_MODE_1M; +#endif + + rc = 1; + if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + /* Get next scheduled item time */ + next_sched_time = ble_ll_conn_get_next_sched_time(connsm); + + txpdu = connsm->cur_tx_pdu; + if (!txpdu) { + pkthdr = STAILQ_FIRST(&connsm->conn_txq); + if (pkthdr) { + txpdu = OS_MBUF_PKTHDR_TO_MBUF(pkthdr); + } + } else { + pkthdr = OS_MBUF_PKTHDR(txpdu); + } + + /* XXX: TODO: need to check this with phy update procedure. There are + limitations if we have started update */ + if (txpdu) { + txhdr = BLE_MBUF_HDR_PTR(txpdu); + rem_bytes = pkthdr->omp_len - txhdr->txinfo.offset; + if (rem_bytes > connsm->eff_max_tx_octets) { + rem_bytes = connsm->eff_max_tx_octets; + } + usecs = ble_ll_pdu_tx_time_get(rem_bytes, tx_phy_mode); + } else { + /* We will send empty pdu (just a LL header) */ + usecs = ble_ll_pdu_tx_time_get(0, tx_phy_mode); + } + usecs += (BLE_LL_IFS * 2) + connsm->eff_max_rx_time; + + ticks = (uint32_t)(next_sched_time - begtime); + allowed_usecs = os_cputime_ticks_to_usecs(ticks); + if ((usecs + add_usecs) >= allowed_usecs) { + rc = 0; + } + } + + return rc; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) +/** + * Callback for the Authenticated payload timer. This function is called + * when the authenticated payload timer expires. When the authenticated + * payload timeout expires, we should + * -> Send the authenticated payload timeout event. + * -> Start the LE ping procedure. + * -> Restart the timer. + * + * @param arg + */ +void +ble_ll_conn_auth_pyld_timer_cb(struct ble_npl_event *ev) +{ + struct ble_ll_conn_sm *connsm; + + connsm = (struct ble_ll_conn_sm *)ble_npl_event_get_arg(ev); + ble_ll_auth_pyld_tmo_event_send(connsm); + ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_LE_PING); + ble_ll_conn_auth_pyld_timer_start(connsm); +} + +void +ble_ll_conn_rd_features_timer_cb(struct ble_npl_event *ev) +{ + struct ble_ll_conn_sm *connsm; + + connsm = (struct ble_ll_conn_sm *)ble_npl_event_get_arg(ev); + + if (!connsm->csmflags.cfbit.pending_hci_rd_features || + !connsm->csmflags.cfbit.rxd_features) { + return; + } + + ble_ll_hci_ev_rd_rem_used_feat(connsm, BLE_ERR_SUCCESS); + connsm->csmflags.cfbit.pending_hci_rd_features = 0; +} + +/** + * Start (or restart) the authenticated payload timer + * + * @param connsm + */ +void +ble_ll_conn_auth_pyld_timer_start(struct ble_ll_conn_sm *connsm) +{ + int32_t tmo; + + /* Timeout in is in 10 msec units */ + tmo = (int32_t)BLE_LL_CONN_AUTH_PYLD_OS_TMO(connsm->auth_pyld_tmo); + ble_npl_callout_reset(&connsm->auth_pyld_timer, tmo); +} +#endif + +static void +ble_ll_conn_master_common_init(struct ble_ll_conn_sm *connsm) +{ + + /* Set master role */ + connsm->conn_role = BLE_LL_CONN_ROLE_MASTER; + + /* Set default ce parameters */ + + /* + * XXX: for now, we need twice the transmit window as our calculations + * for the transmit window offset could be off. + */ + connsm->tx_win_size = BLE_LL_CONN_TX_WIN_MIN + 1; + connsm->tx_win_off = 0; + connsm->master_sca = MYNEWT_VAL(BLE_LL_MASTER_SCA); + + /* Hop increment is a random value between 5 and 16. */ + connsm->hop_inc = (rand() % 12) + 5; + + /* Set channel map to map requested by host */ + connsm->num_used_chans = g_ble_ll_conn_params.num_used_chans; + memcpy(connsm->chanmap, g_ble_ll_conn_params.master_chan_map, + BLE_LL_CONN_CHMAP_LEN); + + /* Calculate random access address and crc initialization value */ + connsm->access_addr = ble_ll_utils_calc_access_addr(); + connsm->crcinit = rand() & 0xffffff; + + /* Set initial schedule callback */ + connsm->conn_sch.sched_cb = ble_ll_conn_event_start_cb; +} +/** + * Called when a create connection command has been received. This initializes + * a connection state machine in the master role. + * + * NOTE: Must be called before the state machine is started + * + * @param connsm + * @param hcc + */ +void +ble_ll_conn_master_init(struct ble_ll_conn_sm *connsm, + struct hci_create_conn *hcc) +{ + + ble_ll_conn_master_common_init(connsm); + + /* Set slave latency and supervision timeout */ + connsm->slave_latency = hcc->conn_latency; + connsm->supervision_tmo = hcc->supervision_timeout; + + /* Set own address type and peer address if needed */ + connsm->own_addr_type = hcc->own_addr_type; + if (hcc->filter_policy == 0) { + memcpy(&connsm->peer_addr, &hcc->peer_addr, BLE_DEV_ADDR_LEN); + connsm->peer_addr_type = hcc->peer_addr_type; + } + + /* XXX: for now, just make connection interval equal to max */ + connsm->conn_itvl = hcc->conn_itvl_max; + + /* Check the min/max CE lengths are less than connection interval */ + if (hcc->min_ce_len > (connsm->conn_itvl * 2)) { + connsm->min_ce_len = connsm->conn_itvl * 2; + } else { + connsm->min_ce_len = hcc->min_ce_len; + } + + if (hcc->max_ce_len > (connsm->conn_itvl * 2)) { + connsm->max_ce_len = connsm->conn_itvl * 2; + } else { + connsm->max_ce_len = hcc->max_ce_len; + } +} + +static void +ble_ll_update_max_tx_octets_phy_mode(struct ble_ll_conn_sm *connsm) +{ + uint32_t usecs; + + usecs = connsm->eff_max_tx_time; + + connsm->max_tx_octets_phy_mode[BLE_PHY_MODE_1M] = + ble_ll_pdu_max_tx_octets_get(usecs, BLE_PHY_MODE_1M); + connsm->max_tx_octets_phy_mode[BLE_PHY_MODE_2M] = + ble_ll_pdu_max_tx_octets_get(usecs, BLE_PHY_MODE_2M); + connsm->max_tx_octets_phy_mode[BLE_PHY_MODE_CODED_125KBPS] = + ble_ll_pdu_max_tx_octets_get(usecs, BLE_PHY_MODE_CODED_125KBPS); + connsm->max_tx_octets_phy_mode[BLE_PHY_MODE_CODED_500KBPS] = + ble_ll_pdu_max_tx_octets_get(usecs, BLE_PHY_MODE_CODED_500KBPS); +} + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + +static void +ble_ll_conn_set_phy(struct ble_ll_conn_sm *connsm, int tx_phy, int rx_phy) +{ + + struct ble_ll_conn_phy_data *phy_data = &connsm->phy_data; + + phy_data->rx_phy_mode = ble_ll_phy_to_phy_mode(rx_phy, + BLE_HCI_LE_PHY_CODED_ANY); + phy_data->cur_rx_phy = rx_phy; + + phy_data->tx_phy_mode = ble_ll_phy_to_phy_mode(tx_phy, + BLE_HCI_LE_PHY_CODED_ANY); + phy_data->cur_tx_phy = tx_phy; + +} + +static void +ble_ll_conn_init_phy(struct ble_ll_conn_sm *connsm, int phy) +{ + struct ble_ll_conn_global_params *conngp; + + /* Always initialize symmetric PHY - controller can change this later */ + ble_ll_conn_set_phy(connsm, phy, phy); + + /* Update data length management to match initial PHY */ + conngp = &g_ble_ll_conn_params; + connsm->max_tx_octets = conngp->conn_init_max_tx_octets; + connsm->max_rx_octets = conngp->supp_max_rx_octets; + if (phy == BLE_PHY_CODED) { + connsm->max_tx_time = conngp->conn_init_max_tx_time_coded; + connsm->max_rx_time = BLE_LL_CONN_SUPP_TIME_MAX_CODED; + connsm->rem_max_tx_time = BLE_LL_CONN_SUPP_TIME_MIN_CODED; + connsm->rem_max_rx_time = BLE_LL_CONN_SUPP_TIME_MIN_CODED; + /* Assume peer does support coded */ + connsm->remote_features[0] |= (BLE_LL_FEAT_LE_CODED_PHY >> 8); + } else { + connsm->max_tx_time = conngp->conn_init_max_tx_time_uncoded; + connsm->max_rx_time = BLE_LL_CONN_SUPP_TIME_MAX_UNCODED; + connsm->rem_max_tx_time = BLE_LL_CONN_SUPP_TIME_MIN_UNCODED; + connsm->rem_max_rx_time = BLE_LL_CONN_SUPP_TIME_MIN_UNCODED; + } + connsm->eff_max_tx_time = connsm->rem_max_tx_time; + connsm->eff_max_rx_time = connsm->rem_max_rx_time; + connsm->rem_max_tx_octets = BLE_LL_CONN_SUPP_BYTES_MIN; + connsm->rem_max_rx_octets = BLE_LL_CONN_SUPP_BYTES_MIN; + connsm->eff_max_tx_octets = BLE_LL_CONN_SUPP_BYTES_MIN; + connsm->eff_max_rx_octets = BLE_LL_CONN_SUPP_BYTES_MIN; + + ble_ll_update_max_tx_octets_phy_mode(connsm); +} + +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + +void +ble_ll_conn_ext_master_init(struct ble_ll_conn_sm *connsm, + struct hci_ext_create_conn *hcc) +{ + + ble_ll_conn_master_common_init(connsm); + + /* Set own address type and peer address if needed */ + connsm->own_addr_type = hcc->own_addr_type; + if (hcc->filter_policy == 0) { + memcpy(&connsm->peer_addr, &hcc->peer_addr, BLE_DEV_ADDR_LEN); + connsm->peer_addr_type = hcc->peer_addr_type; + } + + connsm->initial_params = *hcc; +} + +void +ble_ll_conn_ext_set_params(struct ble_ll_conn_sm *connsm, + struct hci_ext_conn_params *hcc_params, int phy) +{ + /* Set slave latency and supervision timeout */ + connsm->slave_latency = hcc_params->conn_latency; + connsm->supervision_tmo = hcc_params->supervision_timeout; + + /* XXX: for now, just make connection interval equal to max */ + connsm->conn_itvl = hcc_params->conn_itvl_max; + + + /* Check the min/max CE lengths are less than connection interval */ + if (hcc_params->min_ce_len > (connsm->conn_itvl * 2)) { + connsm->min_ce_len = connsm->conn_itvl * 2; + } else { + connsm->min_ce_len = hcc_params->min_ce_len; + } + + if (hcc_params->max_ce_len > (connsm->conn_itvl * 2)) { + connsm->max_ce_len = connsm->conn_itvl * 2; + } else { + connsm->max_ce_len = hcc_params->max_ce_len; + } + + ble_ll_conn_calc_itvl_ticks(connsm); + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + ble_ll_conn_init_phy(connsm, phy); +#endif +} + + +#endif + +static void +ble_ll_conn_set_csa(struct ble_ll_conn_sm *connsm, bool chsel) +{ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) + if (chsel) { + CONN_F_CSA2_SUPP(connsm) = 1; + connsm->channel_id = ((connsm->access_addr & 0xffff0000) >> 16) ^ + (connsm->access_addr & 0x0000ffff); + + /* calculate the next data channel */ + connsm->data_chan_index = ble_ll_conn_calc_dci(connsm, 0); + return; + } +#endif + + connsm->last_unmapped_chan = 0; + + /* calculate the next data channel */ + connsm->data_chan_index = ble_ll_conn_calc_dci(connsm, 1); +} + +/** + * Create a new connection state machine. This is done once per + * connection when the HCI command "create connection" is issued to the + * controller or when a slave receives a connect request. + * + * Context: Link Layer task + * + * @param connsm + */ +void +ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm) +{ + struct ble_ll_conn_global_params *conn_params; + + /* Reset following elements */ + connsm->csmflags.conn_flags = 0; + connsm->event_cntr = 0; + connsm->conn_state = BLE_LL_CONN_STATE_IDLE; + connsm->disconnect_reason = 0; + connsm->rxd_disconnect_reason = 0; + connsm->conn_features = BLE_LL_CONN_INITIAL_FEATURES; + memset(connsm->remote_features, 0, sizeof(connsm->remote_features)); + connsm->vers_nr = 0; + connsm->comp_id = 0; + connsm->sub_vers_nr = 0; + connsm->reject_reason = BLE_ERR_SUCCESS; + connsm->conn_rssi = BLE_LL_CONN_UNKNOWN_RSSI; + connsm->rpa_index = -1; + connsm->inita_identity_used = 0; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) + connsm->sync_transfer_sync_timeout = g_ble_ll_conn_sync_transfer_params.sync_timeout_us; + connsm->sync_transfer_mode = g_ble_ll_conn_sync_transfer_params.mode; + connsm->sync_transfer_skip = g_ble_ll_conn_sync_transfer_params.max_skip; +#endif + + /* XXX: TODO set these based on PHY that started connection */ +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + connsm->phy_data.cur_tx_phy = BLE_PHY_1M; + connsm->phy_data.cur_rx_phy = BLE_PHY_1M; + connsm->phy_data.tx_phy_mode = BLE_PHY_MODE_1M; + connsm->phy_data.rx_phy_mode = BLE_PHY_MODE_1M; + connsm->phy_data.req_pref_tx_phys_mask = 0; + connsm->phy_data.req_pref_rx_phys_mask = 0; + connsm->phy_data.host_pref_tx_phys_mask = g_ble_ll_data.ll_pref_tx_phys; + connsm->phy_data.host_pref_rx_phys_mask = g_ble_ll_data.ll_pref_rx_phys; + connsm->phy_data.phy_options = 0; + connsm->phy_tx_transition = 0; +#endif + + /* Reset current control procedure */ + connsm->cur_ctrl_proc = BLE_LL_CTRL_PROC_IDLE; + connsm->pending_ctrl_procs = 0; + + /* + * Set handle in connection update procedure to 0. If the handle + * is non-zero it means that the host initiated the connection + * parameter update request and the rest of the parameters are valid. + */ + connsm->conn_param_req.handle = 0; + + /* Connection end event */ + ble_npl_event_init(&connsm->conn_ev_end, ble_ll_conn_event_end, connsm); + + /* Initialize transmit queue and ack/flow control elements */ + STAILQ_INIT(&connsm->conn_txq); + connsm->cur_tx_pdu = NULL; + connsm->tx_seqnum = 0; + connsm->next_exp_seqnum = 0; + connsm->cons_rxd_bad_crc = 0; + connsm->last_rxd_sn = 1; + connsm->completed_pkts = 0; + + /* initialize data length mgmt */ + conn_params = &g_ble_ll_conn_params; + connsm->max_tx_octets = conn_params->conn_init_max_tx_octets; + connsm->max_rx_octets = conn_params->supp_max_rx_octets; + connsm->max_tx_time = conn_params->conn_init_max_tx_time; + connsm->max_rx_time = conn_params->supp_max_rx_time; + connsm->rem_max_tx_time = BLE_LL_CONN_SUPP_TIME_MIN; + connsm->rem_max_rx_time = BLE_LL_CONN_SUPP_TIME_MIN; + connsm->eff_max_tx_time = BLE_LL_CONN_SUPP_TIME_MIN; + connsm->eff_max_rx_time = BLE_LL_CONN_SUPP_TIME_MIN; + connsm->rem_max_tx_octets = BLE_LL_CONN_SUPP_BYTES_MIN; + connsm->rem_max_rx_octets = BLE_LL_CONN_SUPP_BYTES_MIN; + connsm->eff_max_tx_octets = BLE_LL_CONN_SUPP_BYTES_MIN; + connsm->eff_max_rx_octets = BLE_LL_CONN_SUPP_BYTES_MIN; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + connsm->host_req_max_tx_time = 0; +#endif + + ble_ll_update_max_tx_octets_phy_mode(connsm); + + /* Reset encryption data */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + memset(&connsm->enc_data, 0, sizeof(struct ble_ll_conn_enc_data)); + connsm->enc_data.enc_state = CONN_ENC_S_UNENCRYPTED; +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) + connsm->auth_pyld_tmo = BLE_LL_CONN_DEF_AUTH_PYLD_TMO; + CONN_F_LE_PING_SUPP(connsm) = 1; + ble_npl_callout_init(&connsm->auth_pyld_timer, + &g_ble_ll_data.ll_evq, + ble_ll_conn_auth_pyld_timer_cb, + connsm); +#endif + + ble_ll_conn_calc_itvl_ticks(connsm); + + /* Add to list of active connections */ + SLIST_INSERT_HEAD(&g_ble_ll_conn_active_list, connsm, act_sle); +} + +void +ble_ll_conn_update_eff_data_len(struct ble_ll_conn_sm *connsm) +{ + int send_event; + uint16_t eff_time; + uint16_t eff_bytes; + + /* Assume no event sent */ + send_event = 0; + + /* See if effective times have changed */ + eff_time = min(connsm->rem_max_tx_time, connsm->max_rx_time); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + if (connsm->phy_data.cur_rx_phy == BLE_PHY_CODED) { + eff_time = max(eff_time, BLE_LL_CONN_SUPP_TIME_MIN_CODED); + } +#endif + if (eff_time != connsm->eff_max_rx_time) { + connsm->eff_max_rx_time = eff_time; + send_event = 1; + } + eff_time = min(connsm->rem_max_rx_time, connsm->max_tx_time); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + if (connsm->phy_data.cur_tx_phy == BLE_PHY_CODED) { + eff_time = max(eff_time, BLE_LL_CONN_SUPP_TIME_MIN_CODED); + } +#endif + if (eff_time != connsm->eff_max_tx_time) { + connsm->eff_max_tx_time = eff_time; + send_event = 1; + + ble_ll_update_max_tx_octets_phy_mode(connsm); + } + eff_bytes = min(connsm->rem_max_tx_octets, connsm->max_rx_octets); + if (eff_bytes != connsm->eff_max_rx_octets) { + connsm->eff_max_rx_octets = eff_bytes; + send_event = 1; + } + eff_bytes = min(connsm->rem_max_rx_octets, connsm->max_tx_octets); + if (eff_bytes != connsm->eff_max_tx_octets) { + connsm->eff_max_tx_octets = eff_bytes; + send_event = 1; + } + + if (send_event) { + ble_ll_hci_ev_datalen_chg(connsm); + } +} + +/** + * Called when a connection is terminated + * + * Context: Link Layer task. + * + * @param connsm + * @param ble_err + */ +void +ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err) +{ + struct os_mbuf *m; + struct os_mbuf_pkthdr *pkthdr; + os_sr_t sr; + + /* Remove scheduler events just in case */ + ble_ll_sched_rmv_elem(&connsm->conn_sch); + + /* In case of the supervision timeout we shall make sure + * that there is no ongoing connection event. It could happen + * because we scheduled connection event before checking connection timeout. + * If connection event managed to start, let us drop it. + */ + OS_ENTER_CRITICAL(sr); + if (g_ble_ll_conn_cur_sm == connsm) { + ble_ll_conn_halt(); + STATS_INC(ble_ll_conn_stats, conn_event_while_tmo); + } + OS_EXIT_CRITICAL(sr); + + /* Stop any control procedures that might be running */ + ble_npl_callout_stop(&connsm->ctrl_proc_rsp_timer); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) + ble_npl_callout_stop(&connsm->auth_pyld_timer); +#endif + + /* Remove from the active connection list */ + SLIST_REMOVE(&g_ble_ll_conn_active_list, connsm, ble_ll_conn_sm, act_sle); + + /* Free the current transmit pdu if there is one. */ + if (connsm->cur_tx_pdu) { + os_mbuf_free_chain(connsm->cur_tx_pdu); + connsm->cur_tx_pdu = NULL; + } + + /* Free all packets on transmit queue */ + while (1) { + /* Get mbuf pointer from packet header pointer */ + pkthdr = STAILQ_FIRST(&connsm->conn_txq); + if (!pkthdr) { + break; + } + STAILQ_REMOVE_HEAD(&connsm->conn_txq, omp_next); + + m = (struct os_mbuf *)((uint8_t *)pkthdr - sizeof(struct os_mbuf)); + os_mbuf_free_chain(m); + } + + /* Make sure events off queue */ + ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &connsm->conn_ev_end); + +#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING) + /* Remove from occupied periods */ + OS_ENTER_CRITICAL(sr); + BLE_LL_ASSERT(g_ble_ll_sched_data.sch_num_occ_periods > 0); + BLE_LL_ASSERT(g_ble_ll_sched_data.sch_occ_period_mask & connsm->period_occ_mask); + --g_ble_ll_sched_data.sch_num_occ_periods; + g_ble_ll_sched_data.sch_occ_period_mask &= ~connsm->period_occ_mask; + OS_EXIT_CRITICAL(sr); +#endif + + /* Connection state machine is now idle */ + connsm->conn_state = BLE_LL_CONN_STATE_IDLE; + + /* + * If we have features and there's pending HCI command, send an event before + * disconnection event so it does make sense to host. + */ + if (connsm->csmflags.cfbit.pending_hci_rd_features && + connsm->csmflags.cfbit.rxd_features) { + ble_ll_hci_ev_rd_rem_used_feat(connsm, BLE_ERR_SUCCESS); + connsm->csmflags.cfbit.pending_hci_rd_features = 0; + } + + /* + * If there is still pending read features request HCI command, send an + * event to complete it. + */ + if (connsm->csmflags.cfbit.pending_hci_rd_features) { + ble_ll_hci_ev_rd_rem_used_feat(connsm, ble_err); + connsm->csmflags.cfbit.pending_hci_rd_features = 0; + } + + /* + * We need to send a disconnection complete event. Connection Complete for + * canceling connection creation is sent from LE Create Connection Cancel + * Command handler. + * + * If the ble error is "success" it means that the reset command was + * received and we should not send an event. + */ + if (ble_err && (ble_err != BLE_ERR_UNK_CONN_ID || + connsm->csmflags.cfbit.terminate_ind_rxd)) { + ble_ll_disconn_comp_event_send(connsm, ble_err); + } + + /* Put connection state machine back on free list */ + STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe); + + /* Log connection end */ + ble_ll_trace_u32x3(BLE_LL_TRACE_ID_CONN_END, connsm->conn_handle, + connsm->event_cntr, (uint32_t)ble_err); +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) +void +ble_ll_conn_get_anchor(struct ble_ll_conn_sm *connsm, uint16_t conn_event, + uint32_t *anchor, uint8_t *anchor_usecs) +{ + uint32_t ticks; + uint32_t itvl; + + itvl = (connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS); + + if ((int16_t)(conn_event - connsm->event_cntr) < 0) { + itvl *= connsm->event_cntr - conn_event; + ticks = os_cputime_usecs_to_ticks(itvl); + *anchor = connsm->anchor_point - ticks; + } else { + itvl *= conn_event - connsm->event_cntr; + ticks = os_cputime_usecs_to_ticks(itvl); + *anchor = connsm->anchor_point + ticks; + } + + *anchor_usecs = connsm->anchor_point_usecs; + *anchor_usecs += (itvl - os_cputime_ticks_to_usecs(ticks)); + if (*anchor_usecs >= 31) { + (*anchor)++; + *anchor_usecs -= 31; + } +} +#endif + +/** + * Called to move to the next connection event. + * + * Context: Link Layer task. + * + * @param connsm + * + * @return int + */ +static int +ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) +{ + uint16_t latency; + uint32_t itvl; + uint32_t cur_ww; + uint32_t max_ww; + struct ble_ll_conn_upd_req *upd; + uint32_t ticks; + uint32_t usecs; + + /* XXX: deal with connection request procedure here as well */ + ble_ll_conn_chk_csm_flags(connsm); + + /* If unable to start terminate procedure, start it now */ + if (connsm->disconnect_reason && !CONN_F_TERMINATE_STARTED(connsm)) { + ble_ll_ctrl_terminate_start(connsm); + } + + if (CONN_F_TERMINATE_STARTED(connsm) && (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE)) { + /* Some of the devices waits whole connection interval to ACK our + * TERMINATE_IND sent as a Slave. Since we are here it means we are still waiting for ACK. + * Make sure we catch it in next connection event. + */ + connsm->slave_latency = 0; + } + + /* + * XXX: TODO Probably want to add checks to see if we need to start + * a control procedure here as an instant may have prevented us from + * starting one. + */ + + /* + * XXX TODO: I think this is technically incorrect. We can allow slave + * latency if we are doing one of these updates as long as we + * know that the master has received the ACK to the PDU that set + * the instant + */ + /* Set event counter to the next connection event that we will tx/rx in */ + itvl = connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS; + latency = 1; + if (connsm->csmflags.cfbit.allow_slave_latency && + !connsm->csmflags.cfbit.conn_update_sched && + !CONN_F_PHY_UPDATE_SCHED(connsm) && + !connsm->csmflags.cfbit.chanmap_update_scheduled) { + if (connsm->csmflags.cfbit.pkt_rxd) { + latency += connsm->slave_latency; + itvl = itvl * latency; + } + } + connsm->event_cntr += latency; + + /* Set next connection event start time */ + /* We can use pre-calculated values for one interval if latency is 1. */ + if (latency == 1) { + connsm->anchor_point += connsm->conn_itvl_ticks; + connsm->anchor_point_usecs += connsm->conn_itvl_usecs; + } else { + uint32_t ticks; + ticks = os_cputime_usecs_to_ticks(itvl); + connsm->anchor_point += ticks; + connsm->anchor_point_usecs += (itvl - os_cputime_ticks_to_usecs(ticks)); + } + if (connsm->anchor_point_usecs >= 31) { + ++connsm->anchor_point; + connsm->anchor_point_usecs -= 31; + } + + /* + * If a connection update has been scheduled and the event counter + * is now equal to the instant, we need to adjust the start of the + * connection by the the transmit window offset. We also copy in the + * update parameters as they now should take effect. + */ + if (connsm->csmflags.cfbit.conn_update_sched && + (connsm->event_cntr == connsm->conn_update_req.instant)) { + + /* Set flag so we send connection update event */ + upd = &connsm->conn_update_req; + if ((connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) || + ((connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) && + IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ)) || + (connsm->conn_itvl != upd->interval) || + (connsm->slave_latency != upd->latency) || + (connsm->supervision_tmo != upd->timeout)) { + connsm->csmflags.cfbit.host_expects_upd_event = 1; + } + + connsm->supervision_tmo = upd->timeout; + connsm->slave_latency = upd->latency; + connsm->tx_win_size = upd->winsize; + connsm->slave_cur_tx_win_usecs = + connsm->tx_win_size * BLE_LL_CONN_TX_WIN_USECS; + connsm->tx_win_off = upd->winoffset; + connsm->conn_itvl = upd->interval; + ble_ll_conn_calc_itvl_ticks(connsm); + if (upd->winoffset != 0) { + usecs = upd->winoffset * BLE_LL_CONN_ITVL_USECS; + ticks = os_cputime_usecs_to_ticks(usecs); + connsm->anchor_point += ticks; + usecs = usecs - os_cputime_ticks_to_usecs(ticks); + connsm->anchor_point_usecs += usecs; + if (connsm->anchor_point_usecs >= 31) { + ++connsm->anchor_point; + connsm->anchor_point_usecs -= 31; + } + } + + /* Reset the starting point of the connection supervision timeout */ + connsm->last_rxd_pdu_cputime = connsm->anchor_point; + + /* Reset update scheduled flag */ + connsm->csmflags.cfbit.conn_update_sched = 0; + } + + /* + * If there is a channel map request pending and we have reached the + * instant, change to new channel map. Note there is a special case here. + * If we received a channel map update with an instant equal to the event + * counter, when we get here the event counter has already been + * incremented by 1. That is why we do a signed comparison and change to + * new channel map once the event counter equals or has passed channel + * map update instant. + */ + if (connsm->csmflags.cfbit.chanmap_update_scheduled && + ((int16_t)(connsm->chanmap_instant - connsm->event_cntr) <= 0)) { + + /* XXX: there is a chance that the control packet is still on + * the queue of the master. This means that we never successfully + * transmitted update request. Would end up killing connection + on slave side. Could ignore it or see if still enqueued. */ + connsm->num_used_chans = + ble_ll_utils_calc_num_used_chans(connsm->req_chanmap); + memcpy(connsm->chanmap, connsm->req_chanmap, BLE_LL_CONN_CHMAP_LEN); + + connsm->csmflags.cfbit.chanmap_update_scheduled = 0; + + ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_CHAN_MAP_UPD); + + /* XXX: host could have resent channel map command. Need to + check to make sure we dont have to restart! */ + } + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + if (CONN_F_PHY_UPDATE_SCHED(connsm) && + (connsm->event_cntr == connsm->phy_instant)) { + + /* Set cur phy to new phy */ + if (connsm->phy_data.new_tx_phy) { + connsm->phy_data.cur_tx_phy = connsm->phy_data.new_tx_phy; + connsm->phy_data.tx_phy_mode = + ble_ll_phy_to_phy_mode(connsm->phy_data.cur_tx_phy, + connsm->phy_data.phy_options); + } + + if (connsm->phy_data.new_rx_phy) { + connsm->phy_data.cur_rx_phy = connsm->phy_data.new_rx_phy; + connsm->phy_data.rx_phy_mode = + ble_ll_phy_to_phy_mode(connsm->phy_data.cur_rx_phy, + connsm->phy_data.phy_options); + } + + /* Clear flags and set flag to send event at next instant */ + CONN_F_PHY_UPDATE_SCHED(connsm) = 0; + CONN_F_PHY_UPDATE_EVENT(connsm) = 1; + + ble_ll_ctrl_phy_update_proc_complete(connsm); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + /* Recalculate effective connection parameters */ + ble_ll_conn_update_eff_data_len(connsm); + + /* + * If PHY in either direction was changed to coded, we assume that peer + * does support LE Coded PHY even if features were not exchanged yet. + * This means that MaxRxTime can be updated to supported max and we need + * initiate DLE to notify peer about the change. + */ + if (((connsm->phy_data.cur_tx_phy == BLE_PHY_CODED) || + (connsm->phy_data.cur_rx_phy == BLE_PHY_CODED)) && + !(connsm->remote_features[0] & (BLE_LL_FEAT_LE_CODED_PHY >> 8))) { + connsm->remote_features[0] |= (BLE_LL_FEAT_LE_CODED_PHY >> 8); + connsm->max_rx_time = BLE_LL_CONN_SUPP_TIME_MAX_CODED; + ble_ll_ctrl_initiate_dle(connsm); + } +#endif + } +#endif + + /* Calculate data channel index of next connection event */ + connsm->data_chan_index = ble_ll_conn_calc_dci(connsm, latency); + + /* + * If we are trying to terminate connection, check if next wake time is + * passed the termination timeout. If so, no need to continue with + * connection as we will time out anyway. + */ + if (CONN_F_TERMINATE_STARTED(connsm)) { + if ((int32_t)(connsm->terminate_timeout - connsm->anchor_point) <= 0) { + return -1; + } + } + + /* + * Calculate ce end time. For a slave, we need to add window widening and + * the transmit window if we still have one. + */ +#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING) + itvl = g_ble_ll_sched_data.sch_ticks_per_period; +#else + itvl = MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) * BLE_LL_SCHED_32KHZ_TICKS_PER_SLOT; +#endif + if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { + + cur_ww = ble_ll_utils_calc_window_widening(connsm->anchor_point, + connsm->last_anchor_point, + connsm->master_sca); + max_ww = (connsm->conn_itvl * (BLE_LL_CONN_ITVL_USECS/2)) - BLE_LL_IFS; + if (cur_ww >= max_ww) { + return -1; + } + cur_ww += BLE_LL_JITTER_USECS; + connsm->slave_cur_window_widening = cur_ww; + itvl += os_cputime_usecs_to_ticks(cur_ww + connsm->slave_cur_tx_win_usecs); + } + itvl -= g_ble_ll_sched_offset_ticks; + connsm->ce_end_time = connsm->anchor_point + itvl; + + return 0; +} + +/** + * Called when a connection has been created. This function will + * -> Set the connection state to created. + * -> Start the connection supervision timer + * -> Set the Link Layer state to connection. + * -> Send a connection complete event. + * + * See Section 4.5.2 Vol 6 Part B + * + * Context: Link Layer + * + * @param connsm + * + * @ return 0: connection NOT created. 1: connection created + */ +static int +ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr) +{ + int rc; + uint8_t *evbuf; + uint32_t endtime; + uint32_t usecs; + + /* XXX: TODO this assumes we received in 1M phy */ + + /* Set state to created */ + connsm->conn_state = BLE_LL_CONN_STATE_CREATED; + + /* Clear packet received flag */ + connsm->csmflags.cfbit.pkt_rxd = 0; + + /* Consider time created the last scheduled time */ + connsm->last_scheduled = os_cputime_get32(); + + /* + * Set the last rxd pdu time since this is where we want to start the + * supervision timer from. + */ + connsm->last_rxd_pdu_cputime = connsm->last_scheduled; + + /* + * Set first connection event time. If slave the endtime is the receive end + * time of the connect request. The actual connection starts 1.25 msecs plus + * the transmit window offset from the end of the connection request. + */ + rc = 1; + if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { + /* + * With a 32.768 kHz crystal we dont care about the remaining usecs + * when setting last anchor point. The only thing last anchor is used + * for is to calculate window widening. The effect of this is + * negligible. + */ + connsm->last_anchor_point = rxhdr->beg_cputime; + + usecs = rxhdr->rem_usecs + 1250 + + (connsm->tx_win_off * BLE_LL_CONN_TX_WIN_USECS) + + ble_ll_pdu_tx_time_get(BLE_CONNECT_REQ_LEN, + rxhdr->rxinfo.phy_mode); + + if (rxhdr->rxinfo.channel < BLE_PHY_NUM_DATA_CHANS) { + switch (rxhdr->rxinfo.phy) { + case BLE_PHY_1M: + case BLE_PHY_2M: + usecs += 1250; + break; + case BLE_PHY_CODED: + usecs += 2500; + break; + default: + BLE_LL_ASSERT(0); + break; + } + } + + /* Anchor point is cputime. */ + endtime = os_cputime_usecs_to_ticks(usecs); + connsm->anchor_point = rxhdr->beg_cputime + endtime; + connsm->anchor_point_usecs = usecs - os_cputime_ticks_to_usecs(endtime); + if (connsm->anchor_point_usecs == 31) { + ++connsm->anchor_point; + connsm->anchor_point_usecs = 0; + } + + connsm->slave_cur_tx_win_usecs = + connsm->tx_win_size * BLE_LL_CONN_TX_WIN_USECS; +#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING) + connsm->ce_end_time = connsm->anchor_point + + g_ble_ll_sched_data.sch_ticks_per_period + + os_cputime_usecs_to_ticks(connsm->slave_cur_tx_win_usecs) + 1; + +#else + connsm->ce_end_time = connsm->anchor_point + + (MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) * BLE_LL_SCHED_32KHZ_TICKS_PER_SLOT) + + os_cputime_usecs_to_ticks(connsm->slave_cur_tx_win_usecs) + 1; +#endif + connsm->slave_cur_window_widening = BLE_LL_JITTER_USECS; + + /* Start the scheduler for the first connection event */ + while (ble_ll_sched_slave_new(connsm)) { + if (ble_ll_conn_next_event(connsm)) { + STATS_INC(ble_ll_conn_stats, cant_set_sched); + rc = 0; + break; + } + } + } + + /* Send connection complete event to inform host of connection */ + if (rc) { +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + /* + * If we have default phy preferences and they are different than + * the current PHY's in use, start update procedure. + */ + /* + * XXX: should we attempt to start this without knowing if + * the other side can support it? + */ + if (!ble_ll_conn_chk_phy_upd_start(connsm)) { + CONN_F_CTRLR_PHY_UPDATE(connsm) = 1; + } +#endif + if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { + ble_ll_adv_send_conn_comp_ev(connsm, rxhdr); + } else { + evbuf = ble_ll_init_get_conn_comp_ev(); + ble_ll_conn_comp_event_send(connsm, BLE_ERR_SUCCESS, evbuf, NULL); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) + ble_ll_hci_ev_le_csa(connsm); +#endif + + /* + * Initiate features exchange + * + * XXX we do this only as a master as it was observed that sending + * LL_SLAVE_FEATURE_REQ after connection breaks some recent iPhone + * models; for slave just assume master will initiate features xchg + * if it has some additional features to use. + */ + ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG); + } + } + + return rc; +} + +/** + * Called upon end of connection event + * + * Context: Link-layer task + * + * @param void *arg Pointer to connection state machine + * + */ +static void +ble_ll_conn_event_end(struct ble_npl_event *ev) +{ + uint8_t ble_err; + uint32_t tmo; + struct ble_ll_conn_sm *connsm; + + ble_ll_rfmgmt_release(); + + /* Better be a connection state machine! */ + connsm = (struct ble_ll_conn_sm *)ble_npl_event_get_arg(ev); + BLE_LL_ASSERT(connsm); + if (connsm->conn_state == BLE_LL_CONN_STATE_IDLE) { + /* That should not happen. If it does it means connection + * is already closed. + * Make sure LL state machine is in idle + */ + STATS_INC(ble_ll_conn_stats, sched_end_in_idle); + BLE_LL_ASSERT(0); + + /* Just in case */ + ble_ll_state_set(BLE_LL_STATE_STANDBY); + + ble_ll_scan_chk_resume(); + return; + } + + /* Log event end */ + ble_ll_trace_u32x2(BLE_LL_TRACE_ID_CONN_EV_END, connsm->conn_handle, + connsm->event_cntr); + + ble_ll_scan_chk_resume(); + + /* If we have transmitted the terminate IND successfully, we are done */ + if ((connsm->csmflags.cfbit.terminate_ind_txd) || + (connsm->csmflags.cfbit.terminate_ind_rxd && + connsm->csmflags.cfbit.terminate_ind_rxd_acked)) { + if (connsm->csmflags.cfbit.terminate_ind_txd) { + ble_err = BLE_ERR_CONN_TERM_LOCAL; + } else { + /* Make sure the disconnect reason is valid! */ + ble_err = connsm->rxd_disconnect_reason; + if (ble_err == 0) { + ble_err = BLE_ERR_REM_USER_CONN_TERM; + } + } + ble_ll_conn_end(connsm, ble_err); + return; + } + + /* Remove any connection end events that might be enqueued */ + ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &connsm->conn_ev_end); + + /* + * If we have received a packet, we can set the current transmit window + * usecs to 0 since we dont need to listen in the transmit window. + */ + if (connsm->csmflags.cfbit.pkt_rxd) { + connsm->slave_cur_tx_win_usecs = 0; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) + /* + * If we are encrypted and have passed the authenticated payload timeout + * we need to send an event to tell the host. Unfortunately, I think we + * need one of these per connection and we have to set this timer + * fairly accurately. So we need to another event in the connection. + * This sucks. + * + * The way this works is that whenever the timer expires it just gets reset + * and we send the autheticated payload timeout event. Note that this timer + * should run even when encryption is paused. + * XXX: what should be here? Was there code here that got deleted? + */ +#endif + + /* Move to next connection event */ + if (ble_ll_conn_next_event(connsm)) { + ble_ll_conn_end(connsm, BLE_ERR_CONN_TERM_LOCAL); + return; + } + + /* Reset "per connection event" variables */ + connsm->cons_rxd_bad_crc = 0; + connsm->csmflags.cfbit.pkt_rxd = 0; + + /* See if we need to start any control procedures */ + ble_ll_ctrl_chk_proc_start(connsm); + + /* Set initial schedule callback */ + connsm->conn_sch.sched_cb = ble_ll_conn_event_start_cb; + + /* XXX: I think all this fine for when we do connection updates, but + we may want to force the first event to be scheduled. Not sure */ + /* Schedule the next connection event */ + while (ble_ll_sched_conn_reschedule(connsm)) { + if (ble_ll_conn_next_event(connsm)) { + ble_ll_conn_end(connsm, BLE_ERR_CONN_TERM_LOCAL); + return; + } + } + + /* + * This is definitely not perfect but hopefully will be fine in regards to + * the specification. We check the supervision timer at connection event + * end. If the next connection event is going to start past the supervision + * timeout we end the connection here. I guess this goes against the spec + * in two ways: + * 1) We are actually causing a supervision timeout before the time + * specified. However, this is really a moot point because the supervision + * timeout would have expired before we could possibly receive a packet. + * 2) We may end the supervision timeout a bit later than specified as + * we only check this at event end and a bad CRC could cause us to continue + * the connection event longer than the supervision timeout. Given that two + * bad CRC's consecutively ends the connection event, I dont regard this as + * a big deal but it could cause a slightly longer supervision timeout. + */ + if (connsm->conn_state == BLE_LL_CONN_STATE_CREATED) { + tmo = (uint32_t)connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS * 6UL; + ble_err = BLE_ERR_CONN_ESTABLISHMENT; + } else { + tmo = connsm->supervision_tmo * BLE_HCI_CONN_SPVN_TMO_UNITS * 1000UL; + ble_err = BLE_ERR_CONN_SPVN_TMO; + } + /* XXX: Convert to ticks to usecs calculation instead??? */ + tmo = os_cputime_usecs_to_ticks(tmo); + if ((int32_t)(connsm->anchor_point - connsm->last_rxd_pdu_cputime) >= tmo) { + ble_ll_conn_end(connsm, ble_err); + return; + } + + /* If we have completed packets, send an event */ + ble_ll_conn_num_comp_pkts_event_send(connsm); + + /* If we have features and there's pending HCI command, send an event */ + if (connsm->csmflags.cfbit.pending_hci_rd_features && + connsm->csmflags.cfbit.rxd_features) { + ble_ll_hci_ev_rd_rem_used_feat(connsm, BLE_ERR_SUCCESS); + connsm->csmflags.cfbit.pending_hci_rd_features = 0; + } +} + +/** + * Update the connection request PDU with the address type and address of + * advertiser we are going to send connect request to. + * + * @param m + * @param adva + * @param addr_type Address type of ADVA from received advertisement. + * @param inita + * @param inita_type Address type of INITA from received advertisement. + + * @param txoffset The tx window offset for this connection + */ +static void +ble_ll_conn_connect_ind_prepare(struct ble_ll_conn_sm *connsm, + struct ble_ll_scan_pdu_data *pdu_data, + uint8_t adva_type, uint8_t *adva, + uint8_t inita_type, uint8_t *inita, + int rpa_index, uint8_t channel) +{ + uint8_t hdr; + uint8_t *addr; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + int is_rpa; + struct ble_ll_resolv_entry *rl; +#endif + + hdr = BLE_ADV_PDU_TYPE_CONNECT_IND; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) + /* We need CSA2 bit only for legacy connect */ + if (channel >= BLE_PHY_NUM_DATA_CHANS) { + hdr |= BLE_ADV_PDU_HDR_CHSEL; + } +#endif + + if (adva_type) { + /* Set random address */ + hdr |= BLE_ADV_PDU_HDR_RXADD_MASK; + } + + if (inita) { + memcpy(pdu_data->inita, inita, BLE_DEV_ADDR_LEN); + if (inita_type) { + hdr |= BLE_ADV_PDU_HDR_TXADD_RAND; + } + } else { + /* Get pointer to our device address */ + connsm = g_ble_ll_conn_create_sm; + if ((connsm->own_addr_type & 1) == 0) { + addr = g_dev_addr; + } else { + hdr |= BLE_ADV_PDU_HDR_TXADD_RAND; + addr = g_random_addr; + } + + /* XXX: do this ahead of time? Calculate the local rpa I mean */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + if (connsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) { + rl = NULL; + is_rpa = ble_ll_is_rpa(adva, adva_type); + if (is_rpa) { + if (rpa_index >= 0) { + rl = &g_ble_ll_resolv_list[rpa_index]; + } + } else { + /* we look for RL entry to generate local RPA regardless if + * resolving is enabled or not (as this is is for local RPA + * not peer RPA) + */ + rl = ble_ll_resolv_list_find(adva, adva_type); + } + + /* + * If peer in on resolving list, we use RPA generated with Local IRK + * from resolving list entry. In other case, we need to use our identity + * address (see Core 5.0, Vol 6, Part B, section 6.4). + */ + if (rl && rl->rl_has_local) { + hdr |= BLE_ADV_PDU_HDR_TXADD_RAND; + ble_ll_resolv_get_priv_addr(rl, 1, pdu_data->inita); + addr = NULL; + } + } +#endif + + if (addr) { + memcpy(pdu_data->inita, addr, BLE_DEV_ADDR_LEN); + /* Identity address used */ + connsm->inita_identity_used = 1; + } + } + + memcpy(pdu_data->adva, adva, BLE_DEV_ADDR_LEN); + + pdu_data->hdr_byte = hdr; +} + +/* Returns true if the address matches the connection peer address having in + * mind privacy mode + */ +static int +ble_ll_conn_is_peer_adv(uint8_t addr_type, uint8_t *adva, int index) +{ + int rc; + uint8_t *peer_addr = NULL; + struct ble_ll_conn_sm *connsm; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + struct ble_ll_resolv_entry *rl; +#endif + + /* XXX: Deal with different types of random addresses here! */ + connsm = g_ble_ll_conn_create_sm; + if (!connsm) { + return 0; + } + + switch (connsm->peer_addr_type) { + /* Fall-through intentional */ + case BLE_HCI_CONN_PEER_ADDR_PUBLIC: + case BLE_HCI_CONN_PEER_ADDR_RANDOM: +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + if (ble_ll_addr_is_id(adva, addr_type)) { + /* Peer uses its identity address. Let's verify privacy mode. + * + * Note: Core Spec 5.0 Vol 6, Part B + * If the Host has added the peer device to the resolving list + * with an all-zero peer IRK, the Controller shall only accept + * the peer's identity address. + */ + if (ble_ll_resolv_enabled()) { + rl = ble_ll_resolv_list_find(adva, addr_type); + if (rl && (rl->rl_priv_mode == BLE_HCI_PRIVACY_NETWORK) && + rl->rl_has_peer) { + return 0; + } + } + } + + /* Check if peer uses RPA. If so and it match, use it as controller + * supports privacy mode + */ + if ((index >= 0) && + (g_ble_ll_resolv_list[index].rl_addr_type == connsm->peer_addr_type)) { + peer_addr = g_ble_ll_resolv_list[index].rl_identity_addr; + } +#endif + /* + * If we are here it means we don't know the device, lets + * check if type is what we are looking for and later + * if address matches + */ + if ((connsm->peer_addr_type == addr_type) && !peer_addr) { + peer_addr = adva; + } + + break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + case BLE_HCI_CONN_PEER_ADDR_PUBLIC_IDENT: + if ((index < 0) || + (g_ble_ll_resolv_list[index].rl_addr_type != 0)) { + return 0; + } + peer_addr = g_ble_ll_resolv_list[index].rl_identity_addr; + break; + case BLE_HCI_CONN_PEER_ADDR_RANDOM_IDENT: + if ((index < 0) || + (g_ble_ll_resolv_list[index].rl_addr_type != 1)) { + return 0; + } + peer_addr = g_ble_ll_resolv_list[index].rl_identity_addr; + break; +#endif + default: + peer_addr = NULL; + break; + } + + rc = 0; + if (peer_addr) { + if (!memcmp(peer_addr, connsm->peer_addr, BLE_DEV_ADDR_LEN)) { + rc = 1; + } + } + + return rc; +} + +static void +ble_ll_conn_connect_ind_txend_to_standby(void *arg) +{ + ble_ll_state_set(BLE_LL_STATE_STANDBY); +} + +static void +ble_ll_conn_connect_ind_txend_to_init(void *arg) +{ + ble_ll_state_set(BLE_LL_STATE_INITIATING); +} + +static uint8_t +ble_ll_conn_connect_ind_tx_pducb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) +{ + struct ble_ll_conn_sm *connsm; + struct ble_ll_scan_pdu_data *pdu_data; + + connsm = pducb_arg; + /* + * pdu_data was prepared just before starting TX and is expected to be + * still valid here + */ + pdu_data = ble_ll_scan_get_pdu_data(); + + memcpy(dptr, pdu_data->inita, BLE_DEV_ADDR_LEN); + memcpy(dptr + BLE_DEV_ADDR_LEN, pdu_data->adva, BLE_DEV_ADDR_LEN); + + dptr += 2 * BLE_DEV_ADDR_LEN; + + put_le32(dptr, connsm->access_addr); + dptr[4] = (uint8_t)connsm->crcinit; + dptr[5] = (uint8_t)(connsm->crcinit >> 8); + dptr[6] = (uint8_t)(connsm->crcinit >> 16); + dptr[7] = connsm->tx_win_size; + put_le16(dptr + 8, connsm->tx_win_off); + put_le16(dptr + 10, connsm->conn_itvl); + put_le16(dptr + 12, connsm->slave_latency); + put_le16(dptr + 14, connsm->supervision_tmo); + memcpy(dptr + 16, &connsm->chanmap, BLE_LL_CONN_CHMAP_LEN); + dptr[21] = connsm->hop_inc | (connsm->master_sca << 5); + + *hdr_byte = pdu_data->hdr_byte; + + return 34; +} + +/** + * Send a connection requestion to an advertiser + * + * Context: Interrupt + * + * @param addr_type Address type of advertiser + * @param adva Address of advertiser + */ +int +ble_ll_conn_connect_ind_send(struct ble_ll_conn_sm *connsm, uint8_t end_trans) +{ + int rc; + + if (end_trans == BLE_PHY_TRANSITION_NONE) { + ble_phy_set_txend_cb(ble_ll_conn_connect_ind_txend_to_standby, NULL); + } else { + ble_phy_set_txend_cb(ble_ll_conn_connect_ind_txend_to_init, NULL); + } + + rc = ble_phy_tx(ble_ll_conn_connect_ind_tx_pducb, connsm, end_trans); + + return rc; +} + +/** + * Called when a schedule item overlaps the currently running connection + * event. This generally should not happen, but if it does we stop the + * current connection event to let the schedule item run. + * + * NOTE: the phy has been disabled as well as the wfr timer before this is + * called. + */ +void +ble_ll_conn_event_halt(void) +{ + ble_ll_state_set(BLE_LL_STATE_STANDBY); + if (g_ble_ll_conn_cur_sm) { + g_ble_ll_conn_cur_sm->csmflags.cfbit.pkt_rxd = 0; + ble_ll_event_send(&g_ble_ll_conn_cur_sm->conn_ev_end); + g_ble_ll_conn_cur_sm = NULL; + } +} + +/** + * Process a received PDU while in the initiating state. + * + * Context: Link Layer task. + * + * @param pdu_type + * @param rxbuf + * @param ble_hdr + */ +void +ble_ll_init_rx_pkt_in(uint8_t pdu_type, uint8_t *rxbuf, + struct ble_mbuf_hdr *ble_hdr) +{ + uint8_t addr_type; + uint8_t *addr; + uint8_t *adv_addr; + uint8_t *inita; + uint8_t inita_type; + struct ble_ll_conn_sm *connsm; + int ext_adv_mode = -1; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + struct ble_ll_aux_data *aux_data = NULL; + + if (ble_hdr->rxinfo.user_data) { + /* aux_data just a local helper, no need to ref + * as ble_hdr->rxinfo.user_data is unref in the end of this function + */ + aux_data = ble_hdr->rxinfo.user_data; + } +#endif + + /* Get the connection state machine we are trying to create */ + connsm = g_ble_ll_conn_create_sm; + if (!connsm) { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (aux_data) { + ble_ll_scan_aux_data_unref(ble_hdr->rxinfo.user_data); + ble_hdr->rxinfo.user_data = NULL; + } +#endif + return; + } + + if (!BLE_MBUF_HDR_CRC_OK(ble_hdr)) { + goto scan_continue; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (BLE_MBUF_HDR_AUX_INVALID(ble_hdr)) { + goto scan_continue; + } + + if (pdu_type == BLE_ADV_PDU_TYPE_ADV_EXT_IND) { + if (BLE_MBUF_HDR_WAIT_AUX(ble_hdr)) { + /* Just continue scanning. We are waiting for AUX */ + if (!ble_ll_sched_aux_scan(ble_hdr, connsm->scansm, aux_data)) { + /* ref for aux ptr in the scheduler */ + ble_ll_scan_aux_data_unref(ble_hdr->rxinfo.user_data); + ble_hdr->rxinfo.user_data = NULL; + ble_ll_scan_chk_resume(); + return; + } + goto scan_continue; + } + } + + if (CONN_F_AUX_CONN_REQ(connsm)) { + if (pdu_type != BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP) { + /* Wait for connection response, in this point of time aux is NULL */ + BLE_LL_ASSERT(ble_hdr->rxinfo.user_data == NULL); + return; + } + } +#endif + + /* If we have sent a connect request, we need to enter CONNECTION state */ + if (connsm && CONN_F_CONN_REQ_TXD(connsm)) { + /* Set address of advertiser to which we are connecting. */ + + if (ble_ll_scan_adv_decode_addr(pdu_type, rxbuf, ble_hdr, + &adv_addr, &addr_type, + &inita, &inita_type, &ext_adv_mode)) { + /* Something got wrong, keep trying to connect */ + goto scan_continue; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + /* + * Did we resolve this address? If so, set correct peer address + * and peer address type. + */ + if (connsm->rpa_index >= 0) { + addr_type = g_ble_ll_resolv_list[connsm->rpa_index].rl_addr_type + 2; + addr = g_ble_ll_resolv_list[connsm->rpa_index].rl_identity_addr; + } else { + addr = adv_addr; + } +#else + addr = adv_addr; +#endif + + if (connsm->rpa_index >= 0) { + connsm->peer_addr_type = addr_type; + memcpy(connsm->peer_addr, addr, BLE_DEV_ADDR_LEN); + + ble_ll_scan_set_peer_rpa(adv_addr); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + /* Update resolving list with current peer RPA */ + ble_ll_resolv_set_peer_rpa(connsm->rpa_index, rxbuf + BLE_LL_PDU_HDR_LEN); + if (ble_ll_is_rpa(inita, inita_type)) { + ble_ll_resolv_set_local_rpa(connsm->rpa_index, inita); + } + +#endif + } else if (ble_ll_scan_whitelist_enabled()) { + /* if WL is used we need to store peer addr also if it was not + * resolved + */ + connsm->peer_addr_type = addr_type; + memcpy(connsm->peer_addr, addr, BLE_DEV_ADDR_LEN); + } + + /* Connection has been created. Stop scanning */ + g_ble_ll_conn_create_sm = NULL; + ble_ll_scan_sm_stop(0); + + /* For AUX Connect CSA2 is mandatory. Otherwise we need to check bit + * mask + */ + if (ble_hdr->rxinfo.channel < BLE_PHY_NUM_DATA_CHANS) { + ble_ll_conn_set_csa(connsm, 1); + } else { + ble_ll_conn_set_csa(connsm, rxbuf[0] & BLE_ADV_PDU_HDR_CHSEL_MASK); + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + /* Lets take last used phy */ + ble_ll_conn_init_phy(connsm, ble_hdr->rxinfo.phy); +#endif + if (aux_data) { + ble_ll_scan_aux_data_unref(ble_hdr->rxinfo.user_data); + ble_hdr->rxinfo.user_data = NULL; + } +#endif + ble_ll_conn_created(connsm, NULL); + return; + } + +scan_continue: +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + /* Drop last reference and keep continue to connect */ + if (aux_data) { + ble_ll_scan_aux_data_unref(ble_hdr->rxinfo.user_data); + ble_hdr->rxinfo.user_data = NULL; + } +#endif + ble_ll_scan_chk_resume(); +} + +/** + * Called when a receive PDU has started and we are in the initiating state. + * + * Context: Interrupt + * + * @param pdu_type + * @param ble_hdr + * + * @return int + * 0: we will not attempt to reply to this frame + * 1: we may send a response to this frame. + */ +int +ble_ll_init_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *ble_hdr) +{ + struct ble_ll_conn_sm *connsm; + + connsm = g_ble_ll_conn_create_sm; + if (!connsm) { + return 0; + } + + if ((pdu_type == BLE_ADV_PDU_TYPE_ADV_IND) || + (pdu_type == BLE_ADV_PDU_TYPE_ADV_DIRECT_IND || + pdu_type == BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP)) { + return 1; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (pdu_type == BLE_ADV_PDU_TYPE_ADV_EXT_IND && + connsm->scansm->ext_scanning) { + if (connsm->scansm->cur_aux_data) { + STATS_INC(ble_ll_stats, aux_received); + } + + ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_EXT_ADV; + return 1; + } +#endif + + return 0; +} + +/** + * Called when a receive PDU has ended and we are in the initiating state. + * + * Context: Interrupt + * + * @param rxpdu + * @param crcok + * @param ble_hdr + * + * @return int + * < 0: Disable the phy after reception. + * == 0: Success. Do not disable the PHY. + * > 0: Do not disable PHY as that has already been done. + */ +int +ble_ll_init_rx_isr_end(uint8_t *rxbuf, uint8_t crcok, + struct ble_mbuf_hdr *ble_hdr) +{ + int rc; + int resolved; + int chk_wl; + int index; + uint8_t pdu_type; + uint8_t adv_addr_type; + uint8_t peer_addr_type; + uint8_t *adv_addr = NULL; + uint8_t *peer; + uint8_t *init_addr = NULL; + uint8_t init_addr_type; + uint8_t pyld_len; + uint8_t inita_is_rpa; + uint8_t conn_req_end_trans; + struct os_mbuf *rxpdu; + struct ble_ll_conn_sm *connsm; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + struct ble_ll_resolv_entry *rl; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + struct ble_ll_scan_sm *scansm; + uint8_t phy; +#endif + int ext_adv_mode = -1; + + /* Get connection state machine to use if connection to be established */ + connsm = g_ble_ll_conn_create_sm; + /* This could happen if connection init was cancelled while isr end was + * already pending + */ + if (!connsm) { + ble_ll_state_set(BLE_LL_STATE_STANDBY); + return -1; + } + + rc = -1; + pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK; + pyld_len = rxbuf[1]; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + scansm = connsm->scansm; + if (scansm->cur_aux_data) { + ble_hdr->rxinfo.user_data = scansm->cur_aux_data; + scansm->cur_aux_data = NULL; + } +#endif + + if (!crcok) { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + /* Invalid packet - make sure we do not wait for AUX_CONNECT_RSP */ + ble_ll_conn_reset_pending_aux_conn_rsp(); +#endif + + /* Ignore this packet */ + goto init_rx_isr_exit; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + /* If we sent AUX_CONNECT_REQ, we only expect AUX_CONNECT_RSP here */ + if (CONN_F_AUX_CONN_REQ(connsm)) { + if (pdu_type != BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP) { + STATS_INC(ble_ll_stats, aux_conn_rsp_err); + CONN_F_CONN_REQ_TXD(connsm) = 0; + CONN_F_AUX_CONN_REQ(connsm) = 0; + ble_ll_sched_rmv_elem(&connsm->conn_sch); + } + goto init_rx_isr_exit; + } +#endif + + inita_is_rpa = 0; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (pdu_type == BLE_ADV_PDU_TYPE_ADV_EXT_IND) { + if (!scansm->ext_scanning) { + goto init_rx_isr_exit; + } + + rc = ble_ll_scan_update_aux_data(ble_hdr, rxbuf, NULL); + if (rc < 0) { + /* No memory or broken packet */ + ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_AUX_INVALID; + goto init_rx_isr_exit; + } + } +#endif + + /* Lets get addresses from advertising report*/ + if (ble_ll_scan_adv_decode_addr(pdu_type, rxbuf, ble_hdr, + &adv_addr, &adv_addr_type, + &init_addr, &init_addr_type, + &ext_adv_mode)) { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_AUX_INVALID; +#endif + goto init_rx_isr_exit; + } + + switch (pdu_type) { + case BLE_ADV_PDU_TYPE_ADV_IND: + break; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + case BLE_ADV_PDU_TYPE_ADV_EXT_IND: + rc = -1; + + /* If this is not connectable adv mode, lets skip it */ + if (!(ext_adv_mode & BLE_LL_EXT_ADV_MODE_CONN)) { + goto init_rx_isr_exit; + } + + if (!adv_addr) { + ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_AUX_PTR_WAIT; + goto init_rx_isr_exit; + } + + if (!init_addr) { + break; + } + /* if there is direct address lets fall down and check it.*/ + // no break +#endif + case BLE_ADV_PDU_TYPE_ADV_DIRECT_IND: + inita_is_rpa = (uint8_t)ble_ll_is_rpa(init_addr, init_addr_type); + if (!inita_is_rpa) { + + /* Resolving will be done later. Check if identity InitA matches */ + if (!ble_ll_is_our_devaddr(init_addr, init_addr_type)) { + goto init_rx_isr_exit; + } + } +#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + else { + /* If privacy is off - reject RPA InitA*/ + goto init_rx_isr_exit; + } +#endif + + break; + default: + goto init_rx_isr_exit; + } + + /* Should we send a connect request? */ + index = -1; + peer = adv_addr; + peer_addr_type = adv_addr_type; + + resolved = 0; + chk_wl = ble_ll_scan_whitelist_enabled(); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + if (ble_ll_is_rpa(adv_addr, adv_addr_type) && ble_ll_resolv_enabled()) { + index = ble_hw_resolv_list_match(); + if (index >= 0) { + rl = &g_ble_ll_resolv_list[index]; + + ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_RESOLVED; + connsm->rpa_index = index; + peer = rl->rl_identity_addr; + peer_addr_type = rl->rl_addr_type; + resolved = 1; + + /* Assure privacy */ + if ((rl->rl_priv_mode == BLE_HCI_PRIVACY_NETWORK) && init_addr && + !inita_is_rpa && rl->rl_has_local) { + goto init_rx_isr_exit; + } + + /* + * If the InitA is a RPA, we must see if it resolves based on the + * identity address of the resolved ADVA. + */ + if (init_addr && inita_is_rpa) { + if (!ble_ll_resolv_rpa(init_addr, + g_ble_ll_resolv_list[index].rl_local_irk)) { + goto init_rx_isr_exit; + } + + /* Core Specification Vol 6, Part B, Section 6.4: + * "The Link Layer should not set the InitA field to the same + * value as the TargetA field in the received advertising PDU." + * + * We update the received PDU directly here, so ble_ll_init_rx_pkt_in + * can process it as is. + */ + memcpy(init_addr, rl->rl_local_rpa, BLE_DEV_ADDR_LEN); + } + + } else { + if (chk_wl) { + goto init_rx_isr_exit; + } + + /* Could not resolved InitA */ + if (init_addr && inita_is_rpa) { + goto init_rx_isr_exit; + } + } + } else if (init_addr) { + + /* If resolving is off and InitA is RPA we reject advertising */ + if (inita_is_rpa && !ble_ll_resolv_enabled()) { + goto init_rx_isr_exit; + } + + /* Let's see if we have IRK with that peer.*/ + rl = ble_ll_resolv_list_find(adv_addr, adv_addr_type); + + /* Lets make sure privacy mode is correct together with InitA in case it + * is identity address + */ + if (rl && !inita_is_rpa && + (rl->rl_priv_mode == BLE_HCI_PRIVACY_NETWORK) && + rl->rl_has_local) { + goto init_rx_isr_exit; + } + + /* + * If the InitA is a RPA, we must see if it resolves based on the + * identity address of the resolved ADVA. + */ + if (inita_is_rpa) { + if (!rl || !ble_ll_resolv_rpa(init_addr, rl->rl_local_irk)) { + goto init_rx_isr_exit; + } + + /* Core Specification Vol 6, Part B, Section 6.4: + * "The Link Layer should not set the InitA field to the same + * value as the TargetA field in the received advertising PDU." + * + * We update the received PDU directly here, so ble_ll_init_rx_pkt_in + * can process it as is. + */ + memcpy(init_addr, rl->rl_local_rpa, BLE_DEV_ADDR_LEN); + } + } +#endif + + /* Check filter policy */ + if (chk_wl) { + if (!ble_ll_whitelist_match(peer, peer_addr_type, resolved)) { + goto init_rx_isr_exit; + } + } else { + /* Must match the connection address */ + if (!ble_ll_conn_is_peer_adv(adv_addr_type, adv_addr, index)) { + goto init_rx_isr_exit; + } + } + ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_DEVMATCH; + + /* For CONNECT_IND we don't go into RX state */ + conn_req_end_trans = BLE_PHY_TRANSITION_NONE; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + /* Check if we should send AUX_CONNECT_REQ and wait for AUX_CONNECT_RSP */ + if (ble_hdr->rxinfo.channel < BLE_PHY_NUM_DATA_CHANS) { + conn_req_end_trans = BLE_PHY_TRANSITION_TX_RX; + } + + if (connsm->scansm->ext_scanning) { + phy = ble_hdr->rxinfo.phy; + + /* Update connection state machine with appropriate parameters for + * certain PHY + */ + ble_ll_conn_ext_set_params(connsm, + &connsm->initial_params.params[phy - 1], + phy); + + } +#endif + + /* Schedule new connection */ + if (ble_ll_sched_master_new(connsm, ble_hdr, pyld_len)) { + STATS_INC(ble_ll_conn_stats, cant_set_sched); + goto init_rx_isr_exit; + } + + /* Prepare data for connect request */ + ble_ll_conn_connect_ind_prepare(connsm, + ble_ll_scan_get_pdu_data(), + adv_addr_type, adv_addr, + init_addr_type, init_addr, + index, ble_hdr->rxinfo.channel); + + /* Setup to transmit the connect request */ + rc = ble_ll_conn_connect_ind_send(connsm, conn_req_end_trans); + if (rc) { + ble_ll_sched_rmv_elem(&connsm->conn_sch); + goto init_rx_isr_exit; + } + + if (init_addr && !inita_is_rpa) { + connsm->inita_identity_used = 1; + } + + CONN_F_CONN_REQ_TXD(connsm) = 1; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (ble_hdr->rxinfo.channel < BLE_PHY_NUM_DATA_CHANS) { + /* Lets wait for AUX_CONNECT_RSP */ + CONN_F_AUX_CONN_REQ(connsm) = 1; + /* Keep aux data until we get scan response */ + scansm->cur_aux_data = ble_hdr->rxinfo.user_data; + ble_hdr->rxinfo.user_data = NULL; + STATS_INC(ble_ll_stats, aux_conn_req_tx); + } +#endif + + STATS_INC(ble_ll_conn_stats, conn_req_txd); + +init_rx_isr_exit: + + /* + * We have to restart receive if we cant hand up pdu. We return 0 so that + * the phy does not get disabled. + */ + rxpdu = ble_ll_rxpdu_alloc(pyld_len + BLE_LL_PDU_HDR_LEN); + if (rxpdu == NULL) { + /* + * XXX: possible allocate the PDU when we start initiating? + * I cannot say I like this solution, but if we cannot allocate a PDU + * to hand up to the LL, we need to remove the connection we just + * scheduled since the connection state machine will not get processed + * by link layer properly. For now, just remove it from the scheduler + */ + if (CONN_F_CONN_REQ_TXD(connsm) == 1) { + CONN_F_CONN_REQ_TXD(connsm) = 0; + CONN_F_AUX_CONN_REQ(connsm) = 0; + ble_ll_sched_rmv_elem(&connsm->conn_sch); + } + ble_phy_restart_rx(); + rc = 0; + } else { + ble_phy_rxpdu_copy(rxbuf, rxpdu); + ble_ll_rx_pdu_in(rxpdu); + } + + if (rc) { + ble_ll_state_set(BLE_LL_STATE_STANDBY); + } + + return rc; +} + +/** + * Function called when a timeout has occurred for a connection. There are + * two types of timeouts: a connection supervision timeout and control + * procedure timeout. + * + * Context: Link Layer task + * + * @param connsm + * @param ble_err + */ +void +ble_ll_conn_timeout(struct ble_ll_conn_sm *connsm, uint8_t ble_err) +{ + int was_current; + os_sr_t sr; + + was_current = 0; + OS_ENTER_CRITICAL(sr); + if (g_ble_ll_conn_cur_sm == connsm) { + ble_ll_conn_current_sm_over(NULL); + was_current = 1; + } + OS_EXIT_CRITICAL(sr); + + /* Check if we need to resume scanning */ + if (was_current) { + ble_ll_scan_chk_resume(); + } + + ble_ll_conn_end(connsm, ble_err); +} + +/** + * Called when a data channel PDU has started that matches the access + * address of the current connection. Note that the CRC of the PDU has not + * been checked yet. + * + * Context: Interrupt + * + * @param rxhdr + */ +int +ble_ll_conn_rx_isr_start(struct ble_mbuf_hdr *rxhdr, uint32_t aa) +{ + struct ble_ll_conn_sm *connsm; + + /* + * Disable wait for response timer since we receive a response. We dont + * care if this is the response we were waiting for or not; the code + * called at receive end will deal with ending the connection event + * if needed + */ + connsm = g_ble_ll_conn_cur_sm; + if (connsm) { + /* Double check access address. Better match connection state machine */ + if (aa != connsm->access_addr) { + STATS_INC(ble_ll_conn_stats, rx_data_pdu_bad_aa); + ble_ll_state_set(BLE_LL_STATE_STANDBY); + ble_ll_event_send(&connsm->conn_ev_end); + g_ble_ll_conn_cur_sm = NULL; + return -1; + } + + /* Set connection handle in mbuf header */ + rxhdr->rxinfo.handle = connsm->conn_handle; + + /* Set flag denoting we have received a packet in connection event */ + connsm->csmflags.cfbit.pkt_rxd = 1; + + /* Connection is established */ + connsm->conn_state = BLE_LL_CONN_STATE_ESTABLISHED; + + /* Set anchor point (and last) if 1st rxd frame in connection event */ + if (connsm->csmflags.cfbit.slave_set_last_anchor) { + connsm->csmflags.cfbit.slave_set_last_anchor = 0; + connsm->last_anchor_point = rxhdr->beg_cputime; + connsm->anchor_point = connsm->last_anchor_point; + connsm->anchor_point_usecs = rxhdr->rem_usecs; + } + } + return 1; +} + +/** + * Called from the Link Layer task when a data PDU has been received + * + * Context: Link layer task + * + * @param rxpdu Pointer to received pdu + * @param rxpdu Pointer to ble mbuf header of received pdu + */ +void +ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr) +{ + uint8_t hdr_byte; + uint8_t rxd_sn; + uint8_t *rxbuf; + uint8_t llid; + uint16_t acl_len; + uint16_t acl_hdr; + struct ble_ll_conn_sm *connsm; + + if (BLE_MBUF_HDR_CRC_OK(hdr)) { + /* XXX: there is a chance that the connection was thrown away and + re-used before processing packets here. Fix this. */ + /* We better have a connection state machine */ + connsm = ble_ll_conn_find_active_conn(hdr->rxinfo.handle); + if (connsm) { + /* Check state machine */ + ble_ll_conn_chk_csm_flags(connsm); + + /* Validate rx data pdu */ + rxbuf = rxpdu->om_data; + hdr_byte = rxbuf[0]; + acl_len = rxbuf[1]; + llid = hdr_byte & BLE_LL_DATA_HDR_LLID_MASK; + + /* + * Check that the LLID and payload length are reasonable. + * Empty payload is only allowed for LLID == 01b. + * */ + if ((llid == 0) || + ((acl_len == 0) && (llid != BLE_LL_LLID_DATA_FRAG))) { + STATS_INC(ble_ll_conn_stats, rx_bad_llid); + goto conn_rx_data_pdu_end; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + /* Check if PDU is allowed when encryption is started. If not, + * terminate connection. + * + * Reference: Core 5.0, Vol 6, Part B, 5.1.3.1 + */ + if ((connsm->enc_data.enc_state > CONN_ENC_S_PAUSE_ENC_RSP_WAIT) && + !ble_ll_ctrl_enc_allowed_pdu_rx(rxpdu)) { + ble_ll_conn_timeout(connsm, BLE_ERR_CONN_TERM_MIC); + goto conn_rx_data_pdu_end; + } +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) + /* + * Reset authenticated payload timeout if valid MIC. NOTE: we dont + * check the MIC failure bit as that would have terminated the + * connection + */ + if ((connsm->enc_data.enc_state == CONN_ENC_S_ENCRYPTED) && + CONN_F_LE_PING_SUPP(connsm) && (acl_len != 0)) { + ble_ll_conn_auth_pyld_timer_start(connsm); + } +#endif + + /* Update RSSI */ + connsm->conn_rssi = hdr->rxinfo.rssi; + + /* + * If we are a slave, we can only start to use slave latency + * once we have received a NESN of 1 from the master + */ + if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { + if (hdr_byte & BLE_LL_DATA_HDR_NESN_MASK) { + connsm->csmflags.cfbit.allow_slave_latency = 1; + } + } + + /* + * Discard the received PDU if the sequence number is the same + * as the last received sequence number + */ + rxd_sn = hdr_byte & BLE_LL_DATA_HDR_SN_MASK; + if (rxd_sn != connsm->last_rxd_sn) { + /* Update last rxd sn */ + connsm->last_rxd_sn = rxd_sn; + + /* No need to do anything if empty pdu */ + if ((llid == BLE_LL_LLID_DATA_FRAG) && (acl_len == 0)) { + goto conn_rx_data_pdu_end; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + /* + * XXX: should we check to see if we are in a state where we + * might expect to get an encrypted PDU? + */ + if (BLE_MBUF_HDR_MIC_FAILURE(hdr)) { + STATS_INC(ble_ll_conn_stats, mic_failures); + ble_ll_conn_timeout(connsm, BLE_ERR_CONN_TERM_MIC); + goto conn_rx_data_pdu_end; + } +#endif + + if (llid == BLE_LL_LLID_CTRL) { + /* Process control frame */ + STATS_INC(ble_ll_conn_stats, rx_ctrl_pdus); + if (ble_ll_ctrl_rx_pdu(connsm, rxpdu)) { + STATS_INC(ble_ll_conn_stats, rx_malformed_ctrl_pdus); + } + } else { + /* Count # of received l2cap frames and byes */ + STATS_INC(ble_ll_conn_stats, rx_l2cap_pdus); + STATS_INCN(ble_ll_conn_stats, rx_l2cap_bytes, acl_len); + + /* NOTE: there should be at least two bytes available */ + BLE_LL_ASSERT(OS_MBUF_LEADINGSPACE(rxpdu) >= 2); + os_mbuf_prepend(rxpdu, 2); + rxbuf = rxpdu->om_data; + + acl_hdr = (llid << 12) | connsm->conn_handle; + put_le16(rxbuf, acl_hdr); + put_le16(rxbuf + 2, acl_len); + ble_hci_trans_ll_acl_tx(rxpdu); + } + + /* NOTE: we dont free the mbuf since we handed it off! */ + return; + } else { + STATS_INC(ble_ll_conn_stats, data_pdu_rx_dup); + } + } else { + STATS_INC(ble_ll_conn_stats, no_conn_sm); + } + } + + /* Free buffer */ +conn_rx_data_pdu_end: + os_mbuf_free_chain(rxpdu); +} + +/** + * Called when a packet has been received while in the connection state. + * + * Context: Interrupt + * + * @param rxpdu + * @param crcok + * + * @return int + * < 0: Disable the phy after reception. + * == 0: Success. Do not disable the PHY. + * > 0: Do not disable PHY as that has already been done. + */ +int +ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) +{ + int rc; + int is_ctrl; + uint8_t hdr_byte; + uint8_t hdr_sn; + uint8_t hdr_nesn; + uint8_t conn_sn; + uint8_t conn_nesn; + uint8_t reply; + uint8_t rem_bytes; + uint8_t opcode = 0; + uint8_t rx_pyld_len; + uint32_t begtime; + uint32_t add_usecs; + struct os_mbuf *txpdu; + struct ble_ll_conn_sm *connsm; + struct os_mbuf *rxpdu; + struct ble_mbuf_hdr *txhdr; + int rx_phy_mode; + + /* Retrieve the header and payload length */ + hdr_byte = rxbuf[0]; + rx_pyld_len = rxbuf[1]; + + /* + * We need to attempt to allocate a buffer here. The reason we do this + * now is that we should not ack the packet if we have no receive + * buffers available. We want to free up our transmit PDU if it was + * acked, but we should not ack the received frame if we cant hand it up. + * NOTE: we hand up empty pdu's to the LL task! + */ + rxpdu = ble_ll_rxpdu_alloc(rx_pyld_len + BLE_LL_PDU_HDR_LEN); + + /* + * We should have a current connection state machine. If we dont, we just + * hand the packet to the higher layer to count it. + */ + rc = -1; + connsm = g_ble_ll_conn_cur_sm; + if (!connsm) { + STATS_INC(ble_ll_conn_stats, rx_data_pdu_no_conn); + goto conn_exit; + } + + /* + * Calculate the end time of the received PDU. NOTE: this looks strange + * but for the 32768 crystal we add the time it takes to send the packet + * to the 'additional usecs' field to save some calculations. + */ + begtime = rxhdr->beg_cputime; +#if BLE_LL_BT5_PHY_SUPPORTED + rx_phy_mode = connsm->phy_data.rx_phy_mode; +#else + rx_phy_mode = BLE_PHY_MODE_1M; +#endif + add_usecs = rxhdr->rem_usecs + + ble_ll_pdu_tx_time_get(rx_pyld_len, rx_phy_mode); + + /* + * Check the packet CRC. A connection event can continue even if the + * received PDU does not pass the CRC check. If we receive two consecutive + * CRC errors we end the conection event. + */ + if (!BLE_MBUF_HDR_CRC_OK(rxhdr)) { + /* + * Increment # of consecutively received CRC errors. If more than + * one we will end the connection event. + */ + ++connsm->cons_rxd_bad_crc; + if (connsm->cons_rxd_bad_crc >= 2) { + reply = 0; + } else { + if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + reply = CONN_F_LAST_TXD_MD(connsm); + } else { + /* A slave always responds with a packet */ + reply = 1; + } + } + } else { + /* Reset consecutively received bad crcs (since this one was good!) */ + connsm->cons_rxd_bad_crc = 0; + + /* Set last valid received pdu time (resets supervision timer) */ + connsm->last_rxd_pdu_cputime = begtime + + os_cputime_usecs_to_ticks(add_usecs); + + /* + * Check for valid LLID before proceeding. We have seen some weird + * things with the PHY where the CRC is OK but we dont have a valid + * LLID. This should really never happen but if it does we will just + * bail. An error stat will get incremented at the LL. + */ + if ((hdr_byte & BLE_LL_DATA_HDR_LLID_MASK) == 0) { + goto conn_exit; + } + + /* Set last received header byte */ + connsm->last_rxd_hdr_byte = hdr_byte; + + is_ctrl = 0; + if ((hdr_byte & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_CTRL) { + is_ctrl = 1; + opcode = rxbuf[2]; + } + + /* + * If SN bit from header does not match NESN in connection, this is + * a resent PDU and should be ignored. + */ + hdr_sn = hdr_byte & BLE_LL_DATA_HDR_SN_MASK; + conn_nesn = connsm->next_exp_seqnum; + if (rxpdu && ((hdr_sn && conn_nesn) || (!hdr_sn && !conn_nesn))) { + connsm->next_exp_seqnum ^= 1; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + if (CONN_F_ENCRYPTED(connsm) && !ble_ll_conn_is_empty_pdu(rxbuf)) { + ++connsm->enc_data.rx_pkt_cntr; + } +#endif + } + + ble_ll_trace_u32x2(BLE_LL_TRACE_ID_CONN_RX, connsm->tx_seqnum, + !!(hdr_byte & BLE_LL_DATA_HDR_NESN_MASK)); + + /* + * Check NESN bit from header. If same as tx seq num, the transmission + * is acknowledged. Otherwise we need to resend this PDU. + */ + if (CONN_F_EMPTY_PDU_TXD(connsm) || connsm->cur_tx_pdu) { + hdr_nesn = hdr_byte & BLE_LL_DATA_HDR_NESN_MASK; + conn_sn = connsm->tx_seqnum; + if ((hdr_nesn && conn_sn) || (!hdr_nesn && !conn_sn)) { + /* We did not get an ACK. Must retry the PDU */ + STATS_INC(ble_ll_conn_stats, data_pdu_txf); + } else { + /* Transmit success */ + connsm->tx_seqnum ^= 1; + STATS_INC(ble_ll_conn_stats, data_pdu_txg); + + /* If we transmitted the empty pdu, clear flag */ + if (CONN_F_EMPTY_PDU_TXD(connsm)) { + CONN_F_EMPTY_PDU_TXD(connsm) = 0; + goto chk_rx_terminate_ind; + } + + /* + * Determine if we should remove packet from queue or if there + * are more fragments to send. + */ + txpdu = connsm->cur_tx_pdu; + if (txpdu) { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + if (connsm->enc_data.tx_encrypted) { + ++connsm->enc_data.tx_pkt_cntr; + } +#endif + txhdr = BLE_MBUF_HDR_PTR(txpdu); + if ((txhdr->txinfo.hdr_byte & BLE_LL_DATA_HDR_LLID_MASK) + == BLE_LL_LLID_CTRL) { + connsm->cur_tx_pdu = NULL; + /* Note: the mbuf is freed by this call */ + rc = ble_ll_ctrl_tx_done(txpdu, connsm); + if (rc) { + /* Means we transmitted a TERMINATE_IND */ + goto conn_exit; + } else { + goto chk_rx_terminate_ind; + } + } + + /* Increment offset based on number of bytes sent */ + txhdr->txinfo.offset += txhdr->txinfo.pyld_len; + if (txhdr->txinfo.offset >= OS_MBUF_PKTLEN(txpdu)) { + /* If l2cap pdu, increment # of completed packets */ + if (txhdr->txinfo.pyld_len != 0) { +#if (BLETEST_THROUGHPUT_TEST == 1) + bletest_completed_pkt(connsm->conn_handle); +#endif + ++connsm->completed_pkts; + if (connsm->completed_pkts > 2) { + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, + &g_ble_ll_data.ll_comp_pkt_ev); + } + } + os_mbuf_free_chain(txpdu); + connsm->cur_tx_pdu = NULL; + } else { + rem_bytes = OS_MBUF_PKTLEN(txpdu) - txhdr->txinfo.offset; + /* Adjust payload for max TX time and octets */ + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + if (is_ctrl && + (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) && + (opcode == BLE_LL_CTRL_PHY_UPDATE_IND)) { + connsm->phy_tx_transition = + ble_ll_ctrl_phy_tx_transition_get(rxbuf[3]); + } +#endif + + rem_bytes = ble_ll_conn_adjust_pyld_len(connsm, rem_bytes); + txhdr->txinfo.pyld_len = rem_bytes; + } + } + } + } + + /* Should we continue connection event? */ + /* If this is a TERMINATE_IND, we have to reply */ +chk_rx_terminate_ind: + /* If we received a terminate IND, we must set some flags */ + if (is_ctrl && (opcode == BLE_LL_CTRL_TERMINATE_IND) + && (rx_pyld_len == (1 + BLE_LL_CTRL_TERMINATE_IND_LEN))) { + connsm->csmflags.cfbit.terminate_ind_rxd = 1; + connsm->rxd_disconnect_reason = rxbuf[3]; + } + + if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + reply = CONN_F_LAST_TXD_MD(connsm) || (hdr_byte & BLE_LL_DATA_HDR_MD_MASK); + } else { + /* A slave always replies */ + reply = 1; + } + } + + /* If reply flag set, send data pdu and continue connection event */ + rc = -1; + if (rx_pyld_len && CONN_F_ENCRYPTED(connsm)) { + rx_pyld_len += BLE_LL_DATA_MIC_LEN; + } + if (reply && ble_ll_conn_can_send_next_pdu(connsm, begtime, add_usecs)) { + rc = ble_ll_conn_tx_pdu(connsm); + } + +conn_exit: + /* Copy the received pdu and hand it up */ + if (rxpdu) { + ble_phy_rxpdu_copy(rxbuf, rxpdu); + ble_ll_rx_pdu_in(rxpdu); + } + + /* Send link layer a connection end event if over */ + if (rc) { + ble_ll_conn_current_sm_over(connsm); + } + + return rc; +} + +/** + * Called to adjust payload length to fit into max effective octets and TX time + * on current PHY. + */ +/** + * Called to enqueue a packet on the transmit queue of a connection. Should + * only be called by the controller. + * + * Context: Link Layer + * + * + * @param connsm + * @param om + */ +void +ble_ll_conn_enqueue_pkt(struct ble_ll_conn_sm *connsm, struct os_mbuf *om, + uint8_t hdr_byte, uint8_t length) +{ + os_sr_t sr; + struct os_mbuf_pkthdr *pkthdr; + struct ble_mbuf_hdr *ble_hdr; + int lifo; + + /* Set mbuf length and packet length if a control PDU */ + if (hdr_byte == BLE_LL_LLID_CTRL) { + om->om_len = length; + OS_MBUF_PKTHDR(om)->omp_len = length; + } + + /* Set BLE transmit header */ + ble_hdr = BLE_MBUF_HDR_PTR(om); + ble_hdr->txinfo.flags = 0; + ble_hdr->txinfo.offset = 0; + ble_hdr->txinfo.hdr_byte = hdr_byte; + + /* + * Initial payload length is calculate when packet is dequeued, there's no + * need to do this now. + */ + + lifo = 0; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + if (connsm->enc_data.enc_state > CONN_ENC_S_ENCRYPTED) { + uint8_t llid; + + /* + * If this is one of the following types we need to insert it at + * head of queue. + */ + llid = ble_hdr->txinfo.hdr_byte & BLE_LL_DATA_HDR_LLID_MASK; + if (llid == BLE_LL_LLID_CTRL) { + switch (om->om_data[0]) { + case BLE_LL_CTRL_TERMINATE_IND: + case BLE_LL_CTRL_REJECT_IND: + case BLE_LL_CTRL_REJECT_IND_EXT: + case BLE_LL_CTRL_START_ENC_REQ: + case BLE_LL_CTRL_START_ENC_RSP: + lifo = 1; + break; + case BLE_LL_CTRL_PAUSE_ENC_RSP: + if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + lifo = 1; + } + break; + case BLE_LL_CTRL_ENC_REQ: + case BLE_LL_CTRL_ENC_RSP: + /* If encryption has been paused, we don't want to send any packets from the + * TX queue, as they would go unencrypted. + */ + if (connsm->enc_data.enc_state == CONN_ENC_S_PAUSED) { + lifo = 1; + } + break; + default: + break; + } + } + } +#endif + + /* Add to transmit queue for the connection */ + pkthdr = OS_MBUF_PKTHDR(om); + OS_ENTER_CRITICAL(sr); + if (lifo) { + STAILQ_INSERT_HEAD(&connsm->conn_txq, pkthdr, omp_next); + } else { + STAILQ_INSERT_TAIL(&connsm->conn_txq, pkthdr, omp_next); + } + OS_EXIT_CRITICAL(sr); +} + +/** + * Data packet from host. + * + * Context: Link Layer task + * + * @param om + * @param handle + * @param length + * + * @return int + */ +void +ble_ll_conn_tx_pkt_in(struct os_mbuf *om, uint16_t handle, uint16_t length) +{ + uint8_t hdr_byte; + uint16_t conn_handle; + uint16_t pb; + struct ble_ll_conn_sm *connsm; + + /* See if we have an active matching connection handle */ + conn_handle = handle & 0x0FFF; + connsm = ble_ll_conn_find_active_conn(conn_handle); + if (connsm) { + /* Construct LL header in buffer (NOTE: pb already checked) */ + pb = handle & 0x3000; + if (pb == 0) { + hdr_byte = BLE_LL_LLID_DATA_START; + } else { + hdr_byte = BLE_LL_LLID_DATA_FRAG; + } + + /* Add to total l2cap pdus enqueue */ + STATS_INC(ble_ll_conn_stats, l2cap_enqueued); + + /* Clear flags field in BLE header */ + ble_ll_conn_enqueue_pkt(connsm, om, hdr_byte, length); + } else { + /* No connection found! */ + STATS_INC(ble_ll_conn_stats, handle_not_found); + os_mbuf_free_chain(om); + } +} + +/** + * Called to set the global channel mask that we use for all connections. + * + * @param num_used_chans + * @param chanmap + */ +void +ble_ll_conn_set_global_chanmap(uint8_t num_used_chans, const uint8_t *chanmap) +{ + struct ble_ll_conn_sm *connsm; + struct ble_ll_conn_global_params *conn_params; + + /* Do nothing if same channel map */ + conn_params = &g_ble_ll_conn_params; + if (!memcmp(conn_params->master_chan_map, chanmap, BLE_LL_CONN_CHMAP_LEN)) { + return; + } + + /* Change channel map and cause channel map update procedure to start */ + conn_params->num_used_chans = num_used_chans; + memcpy(conn_params->master_chan_map, chanmap, BLE_LL_CONN_CHMAP_LEN); + + /* Perform channel map update */ + SLIST_FOREACH(connsm, &g_ble_ll_conn_active_list, act_sle) { + if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_CHAN_MAP_UPD); + } + } +} + +/** + * Called when a device has received a connect request while advertising and + * the connect request has passed the advertising filter policy and is for + * us. This will start a connection in the slave role assuming that we dont + * already have a connection with this device and that the connect request + * parameters are valid. + * + * Context: Link Layer + * + * @param rxbuf Pointer to received Connect Request PDU + * + * @return 0: connection not started; 1 connecton started + */ +int +ble_ll_conn_slave_start(uint8_t *rxbuf, uint8_t pat, struct ble_mbuf_hdr *rxhdr, + bool force_csa2) +{ + int rc; + uint32_t temp; + uint32_t crcinit; + uint8_t *inita; + uint8_t *dptr; + struct ble_ll_conn_sm *connsm; + + /* Ignore the connection request if we are already connected*/ + inita = rxbuf + BLE_LL_PDU_HDR_LEN; + SLIST_FOREACH(connsm, &g_ble_ll_conn_active_list, act_sle) { + if (!memcmp(&connsm->peer_addr, inita, BLE_DEV_ADDR_LEN)) { + if (rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK) { + if (connsm->peer_addr_type & 1) { + return 0; + } + } else { + if ((connsm->peer_addr_type & 1) == 0) { + return 0; + } + } + } + } + + /* Allocate a connection. If none available, dont do anything */ + connsm = ble_ll_conn_sm_get(); + if (connsm == NULL) { + return 0; + } + + /* Set the pointer at the start of the connection data */ + dptr = rxbuf + BLE_LL_CONN_REQ_ADVA_OFF + BLE_DEV_ADDR_LEN; + + /* Set connection state machine information */ + connsm->access_addr = get_le32(dptr); + crcinit = dptr[6]; + crcinit = (crcinit << 8) | dptr[5]; + crcinit = (crcinit << 8) | dptr[4]; + connsm->crcinit = crcinit; + connsm->tx_win_size = dptr[7]; + connsm->tx_win_off = get_le16(dptr + 8); + connsm->conn_itvl = get_le16(dptr + 10); + connsm->slave_latency = get_le16(dptr + 12); + connsm->supervision_tmo = get_le16(dptr + 14); + memcpy(&connsm->chanmap, dptr + 16, BLE_LL_CONN_CHMAP_LEN); + connsm->hop_inc = dptr[21] & 0x1F; + connsm->master_sca = dptr[21] >> 5; + + /* Error check parameters */ + if ((connsm->tx_win_off > connsm->conn_itvl) || + (connsm->conn_itvl < BLE_HCI_CONN_ITVL_MIN) || + (connsm->conn_itvl > BLE_HCI_CONN_ITVL_MAX) || + (connsm->tx_win_size < BLE_LL_CONN_TX_WIN_MIN) || + (connsm->slave_latency > BLE_LL_CONN_SLAVE_LATENCY_MAX)) { + goto err_slave_start; + } + + /* Slave latency cannot cause a supervision timeout */ + temp = (connsm->slave_latency + 1) * (connsm->conn_itvl * 2) * + BLE_LL_CONN_ITVL_USECS; + if ((connsm->supervision_tmo * 10000) <= temp ) { + goto err_slave_start; + } + + /* + * The transmit window must be less than or equal to the lesser of 10 + * msecs or the connection interval minus 1.25 msecs. + */ + temp = connsm->conn_itvl - 1; + if (temp > 8) { + temp = 8; + } + if (connsm->tx_win_size > temp) { + goto err_slave_start; + } + + /* Set the address of device that we are connecting with */ + memcpy(&connsm->peer_addr, inita, BLE_DEV_ADDR_LEN); + connsm->peer_addr_type = pat; + + /* Calculate number of used channels; make sure it meets min requirement */ + connsm->num_used_chans = ble_ll_utils_calc_num_used_chans(connsm->chanmap); + if (connsm->num_used_chans < 2) { + goto err_slave_start; + } + + /* Start the connection state machine */ + connsm->conn_role = BLE_LL_CONN_ROLE_SLAVE; + ble_ll_conn_sm_new(connsm); + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + /* Use the same PHY as we received CONNECT_REQ on */ + ble_ll_conn_init_phy(connsm, rxhdr->rxinfo.phy); +#endif + + ble_ll_conn_set_csa(connsm, + force_csa2 || (rxbuf[0] & BLE_ADV_PDU_HDR_CHSEL_MASK)); + + /* Set initial schedule callback */ + connsm->conn_sch.sched_cb = ble_ll_conn_event_start_cb; + rc = ble_ll_conn_created(connsm, rxhdr); + if (!rc) { + SLIST_REMOVE(&g_ble_ll_conn_active_list, connsm, ble_ll_conn_sm, act_sle); + STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe); + } + return rc; + +err_slave_start: + STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe); + STATS_INC(ble_ll_conn_stats, slave_rxd_bad_conn_req_params); + return 0; +} + +#define MAX_TIME_UNCODED(_maxbytes) \ + ble_ll_pdu_tx_time_get(_maxbytes + BLE_LL_DATA_MIC_LEN, \ + BLE_PHY_MODE_1M); +#define MAX_TIME_CODED(_maxbytes) \ + ble_ll_pdu_tx_time_get(_maxbytes + BLE_LL_DATA_MIC_LEN, \ + BLE_PHY_MODE_CODED_125KBPS); + +/** + * Called to reset the connection module. When this function is called the + * scheduler has been stopped and the phy has been disabled. The LL should + * be in the standby state. + * + * Context: Link Layer task + */ +void +ble_ll_conn_module_reset(void) +{ + uint8_t max_phy_pyld; + uint16_t maxbytes; + struct ble_ll_conn_sm *connsm; + struct ble_ll_conn_global_params *conn_params; + + /* Kill the current one first (if one is running) */ + if (g_ble_ll_conn_cur_sm) { + connsm = g_ble_ll_conn_cur_sm; + g_ble_ll_conn_cur_sm = NULL; + ble_ll_conn_end(connsm, BLE_ERR_SUCCESS); + } + + /* Free the global connection complete event if there is one */ + if (g_ble_ll_conn_comp_ev) { + ble_hci_trans_buf_free(g_ble_ll_conn_comp_ev); + g_ble_ll_conn_comp_ev = NULL; + } + + /* Reset connection we are attempting to create */ + g_ble_ll_conn_create_sm = NULL; + + /* Now go through and end all the connections */ + while (1) { + connsm = SLIST_FIRST(&g_ble_ll_conn_active_list); + if (!connsm) { + break; + } + ble_ll_conn_end(connsm, BLE_ERR_SUCCESS); + } + + /* Get the maximum supported PHY PDU size from the PHY */ + max_phy_pyld = ble_phy_max_data_pdu_pyld(); + + /* Configure the global LL parameters */ + conn_params = &g_ble_ll_conn_params; + + maxbytes = min(MYNEWT_VAL(BLE_LL_SUPP_MAX_RX_BYTES), max_phy_pyld); + conn_params->supp_max_rx_octets = maxbytes; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + conn_params->supp_max_rx_time = MAX_TIME_CODED(maxbytes); +#else + conn_params->supp_max_rx_time = MAX_TIME_UNCODED(maxbytes); +#endif + + maxbytes = min(MYNEWT_VAL(BLE_LL_SUPP_MAX_TX_BYTES), max_phy_pyld); + conn_params->supp_max_tx_octets = maxbytes; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + conn_params->supp_max_tx_time = MAX_TIME_CODED(maxbytes); +#else + conn_params->supp_max_tx_time = MAX_TIME_UNCODED(maxbytes); +#endif + + maxbytes = min(MYNEWT_VAL(BLE_LL_CONN_INIT_MAX_TX_BYTES), max_phy_pyld); + conn_params->conn_init_max_tx_octets = maxbytes; + conn_params->conn_init_max_tx_time = MAX_TIME_UNCODED(maxbytes); + conn_params->conn_init_max_tx_time_uncoded = MAX_TIME_UNCODED(maxbytes); + conn_params->conn_init_max_tx_time_coded = MAX_TIME_CODED(maxbytes); + + conn_params->sugg_tx_octets = BLE_LL_CONN_SUPP_BYTES_MIN; + conn_params->sugg_tx_time = BLE_LL_CONN_SUPP_TIME_MIN; + + /* Mask in all channels by default */ + conn_params->num_used_chans = BLE_PHY_NUM_DATA_CHANS; + memset(conn_params->master_chan_map, 0xff, BLE_LL_CONN_CHMAP_LEN - 1); + conn_params->master_chan_map[4] = 0x1f; + + /* Reset statistics */ + STATS_RESET(ble_ll_conn_stats); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) + /* reset default sync transfer params */ + g_ble_ll_conn_sync_transfer_params.max_skip = 0; + g_ble_ll_conn_sync_transfer_params.mode = 0; + g_ble_ll_conn_sync_transfer_params.sync_timeout_us = 0; +#endif +} + +/* Initialize the connection module */ +void +ble_ll_conn_module_init(void) +{ + int rc; + uint16_t i; + struct ble_ll_conn_sm *connsm; + + /* Initialize list of active conections */ + SLIST_INIT(&g_ble_ll_conn_active_list); + STAILQ_INIT(&g_ble_ll_conn_free_list); + + /* + * Take all the connections off the free memory pool and add them to + * the free connection list, assigning handles in linear order. Note: + * the specification allows a handle of zero; we just avoid using it. + */ + connsm = &g_ble_ll_conn_sm[0]; + for (i = 0; i < MYNEWT_VAL(BLE_MAX_CONNECTIONS); ++i) { + + memset(connsm, 0, sizeof(struct ble_ll_conn_sm)); + connsm->conn_handle = i + 1; + STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe); + + /* Initialize fixed schedule elements */ + connsm->conn_sch.sched_type = BLE_LL_SCHED_TYPE_CONN; + connsm->conn_sch.cb_arg = connsm; + ++connsm; + } + + /* Register connection statistics */ + rc = stats_init_and_reg(STATS_HDR(ble_ll_conn_stats), + STATS_SIZE_INIT_PARMS(ble_ll_conn_stats, STATS_SIZE_32), + STATS_NAME_INIT_PARMS(ble_ll_conn_stats), + "ble_ll_conn"); + BLE_LL_ASSERT(rc == 0); + + /* Call reset to finish reset of initialization */ + ble_ll_conn_module_reset(); +} + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn_hci.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn_hci.c new file mode 100644 index 000000000..19ceebf50 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn_hci.c @@ -0,0 +1,1898 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef ESP_PLATFORM + +#include +#include +#include +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/include/nimble/nimble_opt.h" +#include "nimble/nimble/include/nimble/hci_common.h" +#include "nimble/nimble/include/nimble/ble_hci_trans.h" +#include "../include/controller/ble_ll.h" +#include "../include/controller/ble_ll_utils.h" +#include "../include/controller/ble_ll_hci.h" +#include "../include/controller/ble_ll_conn.h" +#include "../include/controller/ble_ll_ctrl.h" +#include "../include/controller/ble_ll_scan.h" +#include "../include/controller/ble_ll_adv.h" +#include "ble_ll_conn_priv.h" + +/* + * Used to limit the rate at which we send the number of completed packets + * event to the host. This is the os time at which we can send an event. + */ +static ble_npl_time_t g_ble_ll_last_num_comp_pkt_evt; +extern uint8_t *g_ble_ll_conn_comp_ev; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +static const uint8_t ble_ll_valid_conn_phy_mask = (BLE_HCI_LE_PHY_1M_PREF_MASK +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) + | BLE_HCI_LE_PHY_2M_PREF_MASK +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + | BLE_HCI_LE_PHY_CODED_PREF_MASK +#endif + ); +static const uint8_t ble_ll_conn_required_phy_mask = (BLE_HCI_LE_PHY_1M_PREF_MASK +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + | BLE_HCI_LE_PHY_CODED_PREF_MASK +#endif + ); +#endif + +/** + * Allocate an event to send a connection complete event when initiating + * + * @return int 0: success -1: failure + */ +static int +ble_ll_init_alloc_conn_comp_ev(void) +{ + int rc; + uint8_t *evbuf; + + rc = 0; + evbuf = g_ble_ll_conn_comp_ev; + if (evbuf == NULL) { + evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (!evbuf) { + rc = -1; + } else { + g_ble_ll_conn_comp_ev = evbuf; + } + } + + return rc; +} + +/** + * Called to check that the connection parameters are within range + * + * @param itvl_min + * @param itvl_max + * @param latency + * @param spvn_tmo + * + * @return int BLE_ERR_INV_HCI_CMD_PARMS if invalid parameters, 0 otherwise + */ +int +ble_ll_conn_hci_chk_conn_params(uint16_t itvl_min, uint16_t itvl_max, + uint16_t latency, uint16_t spvn_tmo) +{ + uint32_t spvn_tmo_usecs; + uint32_t min_spvn_tmo_usecs; + + if ((itvl_min > itvl_max) || + (itvl_min < BLE_HCI_CONN_ITVL_MIN) || + (itvl_max > BLE_HCI_CONN_ITVL_MAX) || + (latency > BLE_HCI_CONN_LATENCY_MAX) || + (spvn_tmo < BLE_HCI_CONN_SPVN_TIMEOUT_MIN) || + (spvn_tmo > BLE_HCI_CONN_SPVN_TIMEOUT_MAX)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* + * Supervision timeout (in msecs) must be more than: + * (1 + connLatency) * connIntervalMax * 1.25 msecs * 2. + */ + spvn_tmo_usecs = spvn_tmo; + spvn_tmo_usecs *= (BLE_HCI_CONN_SPVN_TMO_UNITS * 1000); + min_spvn_tmo_usecs = (uint32_t)itvl_max * 2 * BLE_LL_CONN_ITVL_USECS; + min_spvn_tmo_usecs *= (1 + latency); + if (spvn_tmo_usecs <= min_spvn_tmo_usecs) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + return BLE_ERR_SUCCESS; +} + +/** + * Send a connection complete event + * + * @param status The BLE error code associated with the event + */ +void +ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status, + uint8_t *evbuf, struct ble_ll_adv_sm *advsm) +{ + struct ble_hci_ev_le_subev_enh_conn_complete *enh_ev; + struct ble_hci_ev_le_subev_conn_complete *ev; + struct ble_hci_ev *hci_ev = (void *) evbuf; + uint8_t *rpa; + + BLE_LL_ASSERT(evbuf); + + if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE)) { + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*enh_ev); + enh_ev = (void *) hci_ev->data; + + memset(enh_ev, 0, sizeof(*enh_ev)); + + enh_ev->subev_code = BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE; + enh_ev->status = status; + + if (connsm) { + enh_ev->conn_handle = htole16(connsm->conn_handle); + enh_ev->role = connsm->conn_role - 1; + enh_ev->peer_addr_type = connsm->peer_addr_type; + memcpy(enh_ev->peer_addr, connsm->peer_addr, BLE_DEV_ADDR_LEN); + + if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + if (connsm->inita_identity_used) { + /* We used identity address in CONNECT_IND which can be just + * fine if + * a) it was direct advertising we replied to and remote uses + * its identity address in device privacy mode or IRK is all + * zeros. + * b) peer uses RPA and this is first time we connect to him + */ + rpa = NULL; + } else if (connsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) { + rpa = ble_ll_scan_get_local_rpa(); + } else { + rpa = NULL; + } + } else { + rpa = ble_ll_adv_get_local_rpa(advsm); + } + + if (rpa) { + memcpy(enh_ev->local_rpa, rpa, BLE_DEV_ADDR_LEN); + } + + /* We need to adjust peer type if device connected using RPA + * and was resolved since RPA needs to be added to HCI event. + */ + if (connsm->peer_addr_type < BLE_HCI_CONN_PEER_ADDR_PUBLIC_IDENT + && (connsm->rpa_index > -1)) { + enh_ev->peer_addr_type += 2; + } + + if (enh_ev->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_RANDOM) { + if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + rpa = ble_ll_scan_get_peer_rpa(); + } else { + rpa = ble_ll_adv_get_peer_rpa(advsm); + } + memcpy(enh_ev->peer_rpa, rpa, BLE_DEV_ADDR_LEN); + } + + enh_ev->conn_itvl = htole16(connsm->conn_itvl); + enh_ev->conn_latency = htole16(connsm->slave_latency); + enh_ev->supervision_timeout = htole16(connsm->supervision_tmo); + enh_ev->mca = connsm->master_sca; + } + + ble_ll_hci_event_send(hci_ev); + return; + } + + if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_CONN_COMPLETE)) { + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*ev); + ev = (void *) hci_ev->data; + + memset(ev, 0, sizeof(*ev)); + + ev->subev_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE; + ev->status = status; + + if (connsm) { + ev->conn_handle = htole16(connsm->conn_handle); + ev->role = connsm->conn_role - 1; + ev->peer_addr_type = connsm->peer_addr_type; + + if (ev->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_RANDOM) { + ev->peer_addr_type -= 2; + } + memcpy(ev->peer_addr, connsm->peer_addr, BLE_DEV_ADDR_LEN); + ev->conn_itvl = htole16(connsm->conn_itvl); + ev->conn_latency = htole16(connsm->slave_latency); + ev->supervision_timeout = htole16(connsm->supervision_tmo); + ev->mca = connsm->master_sca; + } + + ble_ll_hci_event_send(hci_ev); + return; + } + + ble_hci_trans_buf_free(evbuf); +} + +/** + * Called to create and send the number of completed packets event to the + * host. + */ +void +ble_ll_conn_num_comp_pkts_event_send(struct ble_ll_conn_sm *connsm) +{ + /** The maximum number of handles that will fit in an event buffer. */ + static const int max_handles = + (BLE_LL_MAX_EVT_LEN - sizeof(struct ble_hci_ev_num_comp_pkts) - 1) / 4; + struct ble_hci_ev_num_comp_pkts *ev; + struct ble_hci_ev *hci_ev; + int event_sent; + + if (connsm == NULL) { + goto skip_conn; + } + + /* + * At some periodic rate, make sure we go through all active connections + * and send the number of completed packet events. We do this mainly + * because the spec says we must update the host even though no packets + * have completed but there are data packets in the controller buffers + * (i.e. enqueued in a connection state machine). + */ + if ((ble_npl_stime_t)(ble_npl_time_get() - g_ble_ll_last_num_comp_pkt_evt) < + ble_npl_time_ms_to_ticks32(MYNEWT_VAL(BLE_LL_NUM_COMP_PKT_ITVL_MS))) { + /* + * If this connection has completed packets, send an event right away. + * We do this to increase throughput but we dont want to search the + * entire active list every time. + */ + if (connsm->completed_pkts) { + hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (hci_ev) { + hci_ev->opcode = BLE_HCI_EVCODE_NUM_COMP_PKTS; + hci_ev->length = sizeof(*ev); + ev = (void *)hci_ev->data; + + ev->count = 1; + ev->completed[0].handle = htole16(connsm->conn_handle); + ev->completed[0].packets = htole16(connsm->completed_pkts); + hci_ev->length += sizeof(ev->completed[0]); + + connsm->completed_pkts = 0; + + ble_ll_hci_event_send(hci_ev); + } + } + return; + } + + /* Iterate through all the active, created connections */ +skip_conn: + hci_ev = NULL; + ev = NULL; + + event_sent = 0; + SLIST_FOREACH(connsm, &g_ble_ll_conn_active_list, act_sle) { + /* + * Only look at connections that we have sent a connection complete + * event and that either has packets enqueued or has completed packets. + */ + if ((connsm->conn_state != BLE_LL_CONN_STATE_IDLE) && + (connsm->completed_pkts || !STAILQ_EMPTY(&connsm->conn_txq))) { + /* If no buffer, get one, If cant get one, leave. */ + if (!hci_ev) { + hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (!hci_ev) { + break; + } + + hci_ev->opcode = BLE_HCI_EVCODE_NUM_COMP_PKTS; + hci_ev->length = sizeof(*ev); + ev = (void *)hci_ev->data; + + ev->count = 0; + } + + /* Add handle and complete packets */ + ev->completed[ev->count].handle = htole16(connsm->conn_handle); + ev->completed[ev->count].packets = htole16(connsm->completed_pkts); + hci_ev->length += sizeof(ev->completed[ev->count]); + ev->count++; + + connsm->completed_pkts = 0; + + /* Send now if the buffer is full. */ + if (ev->count == max_handles) { + ble_ll_hci_event_send(hci_ev); + hci_ev = NULL; + event_sent = 1; + } + } + } + + /* Send event if there is an event to send */ + if (hci_ev) { + ble_ll_hci_event_send(hci_ev); + event_sent = 1; + } + + if (event_sent) { + g_ble_ll_last_num_comp_pkt_evt = ble_npl_time_get(); + } +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) +/** + * Send a authenticated payload timeout event + * + * NOTE: we currently only send this event when we have a reason to send it; + * not when it fails. + * + * @param reason The BLE error code to send as a disconnect reason + */ +void +ble_ll_auth_pyld_tmo_event_send(struct ble_ll_conn_sm *connsm) +{ + struct ble_hci_ev_auth_pyld_tmo *ev; + struct ble_hci_ev *hci_ev; + + if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_AUTH_PYLD_TMO)) { + hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (hci_ev) { + hci_ev->opcode = BLE_HCI_EVCODE_AUTH_PYLD_TMO; + hci_ev->length = sizeof(*ev); + + ev = (void *) hci_ev->data; + ev->conn_handle = htole16(connsm->conn_handle); + + ble_ll_hci_event_send(hci_ev); + } + } +} +#endif + +/** + * Send a disconnection complete event. + * + * NOTE: we currently only send this event when we have a reason to send it; + * not when it fails. + * + * @param reason The BLE error code to send as a disconnect reason + */ +void +ble_ll_disconn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t reason) +{ + struct ble_hci_ev_disconn_cmp *ev; + struct ble_hci_ev *hci_ev; + + if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_DISCONN_CMP)) { + hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (hci_ev) { + hci_ev->opcode = BLE_HCI_EVCODE_DISCONN_CMP; + hci_ev->length = sizeof(*ev); + + ev = (void *) hci_ev->data; + + ev->status = BLE_ERR_SUCCESS; + ev->conn_handle = htole16(connsm->conn_handle); + ev->reason = reason; + + ble_ll_hci_event_send(hci_ev); + } + } +} + +static int +ble_ll_conn_hci_chk_scan_params(uint16_t itvl, uint16_t window) +{ + /* Check interval and window */ + if ((itvl < BLE_HCI_SCAN_ITVL_MIN) || + (itvl > BLE_HCI_SCAN_ITVL_MAX) || + (window < BLE_HCI_SCAN_WINDOW_MIN) || + (window > BLE_HCI_SCAN_WINDOW_MAX) || + (itvl < window)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + return 0; +} + +/** + * Process the HCI command to create a connection. + * + * Context: Link Layer task (HCI command processing) + * + * @param cmdbuf + * + * @return int + */ +int +ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_create_conn_cp *cmd = (const void *) cmdbuf; + struct ble_ll_conn_sm *connsm; + struct hci_create_conn hcc = { 0 }; + int rc; + + if (len < sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* If we are already creating a connection we should leave */ + if (g_ble_ll_conn_create_sm) { + return BLE_ERR_CMD_DISALLOWED; + } + + /* If already enabled, we return an error */ + if (ble_ll_scan_enabled()) { + return BLE_ERR_CMD_DISALLOWED; + } + + /* Retrieve command data */ + hcc.scan_itvl = le16toh(cmd->scan_itvl); + hcc.scan_window = le16toh(cmd->scan_window); + + rc = ble_ll_conn_hci_chk_scan_params(hcc.scan_itvl, hcc.scan_window); + if (rc) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Check filter policy */ + hcc.filter_policy = cmd->filter_policy; + if (hcc.filter_policy > BLE_HCI_INITIATOR_FILT_POLICY_MAX) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Get peer address type and address only if no whitelist used */ + if (hcc.filter_policy == 0) { + hcc.peer_addr_type = cmd->peer_addr_type; + if (hcc.peer_addr_type > BLE_HCI_CONN_PEER_ADDR_MAX) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + memcpy(&hcc.peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN); + } + + /* Get own address type (used in connection request) */ + hcc.own_addr_type = cmd->own_addr_type; + if (hcc.own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Check connection interval, latency and supervision timeoout */ + hcc.conn_itvl_min = le16toh(cmd->min_conn_itvl); + hcc.conn_itvl_max = le16toh(cmd->max_conn_itvl); + hcc.conn_latency = le16toh(cmd->conn_latency); + hcc.supervision_timeout = le16toh(cmd->tmo); + rc = ble_ll_conn_hci_chk_conn_params(hcc.conn_itvl_min, + hcc.conn_itvl_max, + hcc.conn_latency, + hcc.supervision_timeout); + if (rc) { + return rc; + } + + /* Min/max connection event lengths */ + hcc.min_ce_len = le16toh(cmd->min_ce); + hcc.max_ce_len = le16toh(cmd->max_ce); + if (hcc.min_ce_len > hcc.max_ce_len) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Make sure we can allocate an event to send the connection complete */ + if (ble_ll_init_alloc_conn_comp_ev()) { + return BLE_ERR_MEM_CAPACITY; + } + + /* Make sure we can accept a connection! */ + connsm = ble_ll_conn_sm_get(); + if (connsm == NULL) { + return BLE_ERR_CONN_LIMIT; + } + + /* Initialize state machine in master role and start state machine */ + ble_ll_conn_master_init(connsm, &hcc); + ble_ll_conn_sm_new(connsm); + /* CSA will be selected when advertising is received */ + + /* Start scanning */ + rc = ble_ll_scan_initiator_start(&hcc, &connsm->scansm); + if (rc) { + SLIST_REMOVE(&g_ble_ll_conn_active_list,connsm,ble_ll_conn_sm,act_sle); + STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe); + } else { + /* Set the connection state machine we are trying to create. */ + g_ble_ll_conn_create_sm = connsm; + } + + return rc; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +static void +ble_ll_conn_hcc_params_set_fallback(struct hci_ext_create_conn *hcc, + const struct hci_ext_conn_params *fallback) +{ + BLE_LL_ASSERT(fallback); + + if (!(hcc->init_phy_mask & BLE_PHY_MASK_1M)) { + hcc->params[0] = *fallback; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) + if (!(hcc->init_phy_mask & BLE_PHY_MASK_2M)) { + hcc->params[1] = *fallback; + } +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + if (!(hcc->init_phy_mask & BLE_PHY_MASK_CODED)) { + hcc->params[2] = *fallback; + } +#endif +} + +int +ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_ext_create_conn_cp *cmd = (const void *) cmdbuf; + const struct conn_params *params = cmd->conn_params; + const struct hci_ext_conn_params *fallback_params = NULL; + struct hci_ext_create_conn hcc = { 0 }; + struct ble_ll_conn_sm *connsm; + int rc; + + /* validate length */ + if (len < sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + len -= sizeof(*cmd); + + /* If we are already creating a connection we should leave */ + if (g_ble_ll_conn_create_sm) { + return BLE_ERR_CMD_DISALLOWED; + } + + /* If already enabled, we return an error */ + if (ble_ll_scan_enabled()) { + return BLE_ERR_CMD_DISALLOWED; + } + + hcc.filter_policy = cmd->filter_policy; + if (hcc.filter_policy > BLE_HCI_INITIATOR_FILT_POLICY_MAX) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + hcc.own_addr_type = cmd->own_addr_type; + if (hcc.own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Validate peer address type only if no whitelist used */ + if (hcc.filter_policy == 0) { + hcc.peer_addr_type = cmd->peer_addr_type; + + if (hcc.peer_addr_type > BLE_HCI_CONN_PEER_ADDR_MAX) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + memcpy(hcc.peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN); + } + + hcc.init_phy_mask = cmd->init_phy_mask; + if (hcc.init_phy_mask & ~ble_ll_valid_conn_phy_mask) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (!(hcc.init_phy_mask & ble_ll_conn_required_phy_mask)) { + /* At least one of those need to be set */ + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (hcc.init_phy_mask & BLE_PHY_MASK_1M) { + if (len < sizeof(*params)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + len -= sizeof(*params); + + hcc.params[0].scan_itvl = le16toh(params->scan_itvl); + hcc.params[0].scan_window = le16toh(params->scan_window); + + rc = ble_ll_conn_hci_chk_scan_params(hcc.params[0].scan_itvl, + hcc.params[0].scan_window); + if (rc) { + return rc; + } + + hcc.params[0].conn_itvl_min = le16toh(params->conn_min_itvl); + hcc.params[0].conn_itvl_max = le16toh(params->conn_min_itvl); + hcc.params[0].conn_latency = le16toh(params->conn_latency); + hcc.params[0].supervision_timeout = le16toh(params->supervision_timeout); + + rc = ble_ll_conn_hci_chk_conn_params(hcc.params[0].conn_itvl_min, + hcc.params[0].conn_itvl_max, + hcc.params[0].conn_latency, + hcc.params[0].supervision_timeout); + if (rc) { + return rc; + } + + /* Min/max connection event lengths */ + hcc.params[0].min_ce_len = le16toh(params->min_ce); + hcc.params[0].max_ce_len = le16toh(params->max_ce); + if (hcc.params[0].min_ce_len > hcc.params[0].max_ce_len) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + fallback_params = &hcc.params[0]; + params++; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) + if (hcc.init_phy_mask & BLE_PHY_MASK_2M) { + if (len < sizeof(*params)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + len -= sizeof(*params); + + hcc.params[1].conn_itvl_min = le16toh(params->conn_min_itvl); + hcc.params[1].conn_itvl_max = le16toh(params->conn_min_itvl); + hcc.params[1].conn_latency = le16toh(params->conn_latency); + hcc.params[1].supervision_timeout = le16toh(params->supervision_timeout); + + rc = ble_ll_conn_hci_chk_conn_params(hcc.params[1].conn_itvl_min, + hcc.params[1].conn_itvl_max, + hcc.params[1].conn_latency, + hcc.params[1].supervision_timeout); + if (rc) { + return rc; + } + + /* Min/max connection event lengths */ + hcc.params[1].min_ce_len = le16toh(params->min_ce); + hcc.params[1].max_ce_len = le16toh(params->max_ce); + if (hcc.params[1].min_ce_len > hcc.params[1].max_ce_len) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + params++; + } +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + if (hcc.init_phy_mask & BLE_PHY_MASK_CODED) { + if (len < sizeof(*params)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + len -= sizeof(*params); + + hcc.params[2].scan_itvl = le16toh(params->scan_itvl); + hcc.params[2].scan_window = le16toh(params->scan_window); + + rc = ble_ll_conn_hci_chk_scan_params(hcc.params[2].scan_itvl, + hcc.params[2].scan_window); + if (rc) { + return rc; + } + + hcc.params[2].conn_itvl_min = le16toh(params->conn_min_itvl); + hcc.params[2].conn_itvl_max = le16toh(params->conn_min_itvl); + hcc.params[2].conn_latency = le16toh(params->conn_latency); + hcc.params[2].supervision_timeout = le16toh(params->supervision_timeout); + + rc = ble_ll_conn_hci_chk_conn_params(hcc.params[2].conn_itvl_min, + hcc.params[2].conn_itvl_max, + hcc.params[2].conn_latency, + hcc.params[2].supervision_timeout); + if (rc) { + return rc; + } + + /* Min/max connection event lengths */ + hcc.params[2].min_ce_len = le16toh(params->min_ce); + hcc.params[2].max_ce_len = le16toh(params->max_ce); + if (hcc.params[2].min_ce_len > hcc.params[2].max_ce_len) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (!fallback_params) { + fallback_params = &hcc.params[2]; + } + params++; + } +#endif + + /* Make sure we can allocate an event to send the connection complete */ + if (ble_ll_init_alloc_conn_comp_ev()) { + return BLE_ERR_MEM_CAPACITY; + } + + /* Make sure we can accept a connection! */ + connsm = ble_ll_conn_sm_get(); + if (connsm == NULL) { + return BLE_ERR_CONN_LIMIT; + } + + ble_ll_conn_hcc_params_set_fallback(&hcc, fallback_params); + + /* Initialize state machine in master role and start state machine */ + ble_ll_conn_ext_master_init(connsm, &hcc); + ble_ll_conn_sm_new(connsm); + + /* CSA will be selected when advertising is received */ + + /* Start scanning */ + rc = ble_ll_scan_ext_initiator_start(&hcc, &connsm->scansm); + if (rc) { + SLIST_REMOVE(&g_ble_ll_conn_active_list,connsm,ble_ll_conn_sm,act_sle); + STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe); + } else { + /* Set the connection state machine we are trying to create. */ + g_ble_ll_conn_create_sm = connsm; + } + + return rc; +} +#endif + +static int +ble_ll_conn_process_conn_params(const struct ble_hci_le_rem_conn_param_rr_cp *cmd, + struct ble_ll_conn_sm *connsm) +{ + int rc; + struct hci_conn_update *hcu; + + /* Retrieve command data */ + hcu = &connsm->conn_param_req; + hcu->handle = connsm->conn_handle; + + BLE_LL_ASSERT(connsm->conn_handle == le16toh(cmd->conn_handle)); + + hcu->conn_itvl_min = le16toh(cmd->conn_itvl_min); + hcu->conn_itvl_max = le16toh(cmd->conn_itvl_max); + hcu->conn_latency = le16toh(cmd->conn_latency); + hcu->supervision_timeout = le16toh(cmd->supervision_timeout); + hcu->min_ce_len = le16toh(cmd->min_ce); + hcu->max_ce_len = le16toh(cmd->max_ce); + + /* Check that parameter values are in range */ + rc = ble_ll_conn_hci_chk_conn_params(hcu->conn_itvl_min, + hcu->conn_itvl_max, + hcu->conn_latency, + hcu->supervision_timeout); + + /* Check valid min/max ce length */ + if (rc || (hcu->min_ce_len > hcu->max_ce_len)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + return rc; +} + +/** + * Called when the host issues the read remote features command + * + * @param cmdbuf + * + * @return int + */ +int +ble_ll_conn_hci_read_rem_features(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_rd_rem_feat_cp *cmd = (const void *) cmdbuf; + struct ble_ll_conn_sm *connsm; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* If no connection handle exit with error */ + connsm = ble_ll_conn_find_active_conn(le16toh(cmd->conn_handle)); + if (!connsm) { + return BLE_ERR_UNK_CONN_ID; + } + + /* If already pending exit with error */ + if (connsm->csmflags.cfbit.pending_hci_rd_features) { + return BLE_ERR_CMD_DISALLOWED; + } + + /* + * Start control procedure if we did not receive peer's features and did not + * start procedure already. + */ + if (!connsm->csmflags.cfbit.rxd_features && + !IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG)) { + if ((connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) && + !(ble_ll_read_supp_features() & BLE_LL_FEAT_SLAVE_INIT)) { + return BLE_ERR_CMD_DISALLOWED; + } + + ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG); + } + + connsm->csmflags.cfbit.pending_hci_rd_features = 1; + + return BLE_ERR_SUCCESS; +} + +/** + * Called to process a connection update command. + * + * @param cmdbuf + * + * @return int + */ +int +ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_conn_update_cp *cmd = (const void *) cmdbuf; + int rc; + uint8_t ctrl_proc; + uint16_t handle; + struct ble_ll_conn_sm *connsm; + struct hci_conn_update *hcu; + + /* + * XXX: must deal with slave not supporting this feature and using + * conn update! Right now, we only check if WE support the connection + * parameters request procedure. We dont check if the remote does. + * We should also be able to deal with sending the parameter request, + * getting an UNKOWN_RSP ctrl pdu and resorting to use normal + * connection update procedure. + */ + + /* If no connection handle exit with error */ + handle = le16toh(cmd->conn_handle); + connsm = ble_ll_conn_find_active_conn(handle); + if (!connsm) { + return BLE_ERR_UNK_CONN_ID; + } + + /* Better not have this procedure ongoing! */ + if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ) || + IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_UPDATE)) { + return BLE_ERR_CMD_DISALLOWED; + } + + /* See if this feature is supported on both sides */ + if ((connsm->conn_features & BLE_LL_FEAT_CONN_PARM_REQ) == 0) { + if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { + return BLE_ERR_UNSUPP_REM_FEATURE; + } + ctrl_proc = BLE_LL_CTRL_PROC_CONN_UPDATE; + } else { + ctrl_proc = BLE_LL_CTRL_PROC_CONN_PARAM_REQ; + } + + /* + * If we are a slave and the master has initiated the procedure already + * we should deny the slave request for now. If we are a master and the + * slave has initiated the procedure, we need to send a reject to the + * slave. + */ + if (connsm->csmflags.cfbit.awaiting_host_reply) { + if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { + return BLE_ERR_LMP_COLLISION; + } else { + connsm->csmflags.cfbit.awaiting_host_reply = 0; + + /* XXX: If this fails no reject ind will be sent! */ + ble_ll_ctrl_reject_ind_send(connsm, connsm->host_reply_opcode, + BLE_ERR_LMP_COLLISION); + } + } + + /* + * If we are a slave and the master has initiated the channel map + * update procedure we should deny the slave request for now. + */ + if (connsm->csmflags.cfbit.chanmap_update_scheduled) { + if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { + return BLE_ERR_DIFF_TRANS_COLL; + } + } + + /* Retrieve command data */ + hcu = &connsm->conn_param_req; + hcu->conn_itvl_min = le16toh(cmd->conn_itvl_min); + hcu->conn_itvl_max = le16toh(cmd->conn_itvl_max); + hcu->conn_latency = le16toh(cmd->conn_latency); + hcu->supervision_timeout = le16toh(cmd->supervision_timeout); + hcu->min_ce_len = le16toh(cmd->min_ce_len); + hcu->max_ce_len = le16toh(cmd->max_ce_len); + if (hcu->min_ce_len > hcu->max_ce_len) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Check that parameter values are in range */ + rc = ble_ll_conn_hci_chk_conn_params(hcu->conn_itvl_min, + hcu->conn_itvl_max, + hcu->conn_latency, + hcu->supervision_timeout); + if (!rc) { + hcu->handle = handle; + + /* Start the control procedure */ + ble_ll_ctrl_proc_start(connsm, ctrl_proc); + } + + return rc; +} + +int +ble_ll_conn_hci_param_rr(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_le_rem_conn_param_rr_cp *cmd = (const void *) cmdbuf; + struct ble_hci_le_rem_conn_param_rr_rp *rsp = (void *) rspbuf; + int rc; + uint8_t *dptr; + uint8_t rsp_opcode; + uint16_t handle; + struct os_mbuf *om; + struct ble_ll_conn_sm *connsm; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + handle = le16toh(cmd->conn_handle); + + /* See if we support this feature */ + if ((ble_ll_read_supp_features() & BLE_LL_FEAT_CONN_PARM_REQ) == 0) { + rc = BLE_ERR_UNKNOWN_HCI_CMD; + goto done; + } + + /* If we dont have a handle we cant do anything */ + connsm = ble_ll_conn_find_active_conn(handle); + if (!connsm) { + rc = BLE_ERR_UNK_CONN_ID; + goto done; + } + + /* Make sure connection parameters are valid */ + rc = ble_ll_conn_process_conn_params(cmd, connsm); + + /* The connection should be awaiting a reply. If not, just discard */ + if (connsm->csmflags.cfbit.awaiting_host_reply) { + /* Get a control packet buffer */ + if (rc == BLE_ERR_SUCCESS) { + om = os_msys_get_pkthdr(BLE_LL_CTRL_MAX_PDU_LEN, + sizeof(struct ble_mbuf_hdr)); + if (om) { + dptr = om->om_data; + rsp_opcode = ble_ll_ctrl_conn_param_reply(connsm, dptr, + &connsm->conn_cp); + dptr[0] = rsp_opcode; + len = g_ble_ll_ctrl_pkt_lengths[rsp_opcode] + 1; + ble_ll_conn_enqueue_pkt(connsm, om, BLE_LL_LLID_CTRL, len); + } + } else { + /* XXX: check return code and deal */ + ble_ll_ctrl_reject_ind_send(connsm, connsm->host_reply_opcode, + BLE_ERR_CONN_PARMS); + } + connsm->csmflags.cfbit.awaiting_host_reply = 0; + + /* XXX: if we cant get a buffer, what do we do? We need to remember + * reason if it was a negative reply. We also would need to have + * some state to tell us this happened + */ + } + +done: + rsp->conn_handle = htole16(handle); + + *rsplen = sizeof(*rsp); + return rc; +} + +int +ble_ll_conn_hci_param_nrr(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_le_rem_conn_params_nrr_cp *cmd = (const void *) cmdbuf; + struct ble_hci_le_rem_conn_params_nrr_rp *rsp = (void *) rspbuf; + struct ble_ll_conn_sm *connsm; + uint16_t handle; + int rc; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + handle = le16toh(cmd->conn_handle); + + /* See if we support this feature */ + if ((ble_ll_read_supp_features() & BLE_LL_FEAT_CONN_PARM_REQ) == 0) { + rc = BLE_ERR_UNKNOWN_HCI_CMD; + goto done; + } + + /* If we dont have a handle we cant do anything */ + connsm = ble_ll_conn_find_active_conn(handle); + if (!connsm) { + rc = BLE_ERR_UNK_CONN_ID; + goto done; + } + + rc = BLE_ERR_SUCCESS; + + /* The connection should be awaiting a reply. If not, just discard */ + if (connsm->csmflags.cfbit.awaiting_host_reply) { + /* XXX: check return code and deal */ + ble_ll_ctrl_reject_ind_send(connsm, connsm->host_reply_opcode, + cmd->reason); + connsm->csmflags.cfbit.awaiting_host_reply = 0; + + /* XXX: if we cant get a buffer, what do we do? We need to remember + * reason if it was a negative reply. We also would need to have + * some state to tell us this happened + */ + } + +done: + rsp->conn_handle = htole16(handle); + + *rsplen = sizeof(*rsp); + return rc; +} + +/* this is called from same context after cmd complete is send so it is + * safe to use g_ble_ll_conn_comp_ev + */ +static void +ble_ll_conn_hci_cancel_conn_complete_event(void) +{ + BLE_LL_ASSERT(g_ble_ll_conn_comp_ev); + + ble_ll_conn_comp_event_send(NULL, BLE_ERR_UNK_CONN_ID, + g_ble_ll_conn_comp_ev, NULL); + g_ble_ll_conn_comp_ev = NULL; +} + +/** + * Called when HCI command to cancel a create connection command has been + * received. + * + * Context: Link Layer (HCI command parser) + * + * @return int + */ +int +ble_ll_conn_create_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb) +{ + int rc; + struct ble_ll_conn_sm *connsm; + os_sr_t sr; + + /* + * If we receive this command and we have not got a connection + * create command, we have to return disallowed. The spec does not say + * what happens if the connection has already been established. We + * return disallowed as well + */ + OS_ENTER_CRITICAL(sr); + connsm = g_ble_ll_conn_create_sm; + if (connsm && (connsm->conn_state == BLE_LL_CONN_STATE_IDLE)) { + /* stop scanning and end the connection event */ + g_ble_ll_conn_create_sm = NULL; + ble_ll_scan_sm_stop(1); + ble_ll_conn_end(connsm, BLE_ERR_UNK_CONN_ID); + + *post_cmd_cb = ble_ll_conn_hci_cancel_conn_complete_event; + + rc = BLE_ERR_SUCCESS; + } else { + /* If we are not attempting to create a connection*/ + rc = BLE_ERR_CMD_DISALLOWED; + } + OS_EXIT_CRITICAL(sr); + + return rc; +} + +/** + * Called to process a HCI disconnect command + * + * Context: Link Layer task (HCI command parser). + * + * @param cmdbuf + * + * @return int + */ +int +ble_ll_conn_hci_disconnect_cmd(const uint8_t *cmdbuf, uint8_t len) +{ + int rc; + uint16_t handle; + struct ble_ll_conn_sm *connsm; + const struct ble_hci_lc_disconnect_cp *cmd = (const void *) cmdbuf; + + if (len != sizeof (*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Check for valid parameters */ + handle = le16toh(cmd->conn_handle); + + rc = BLE_ERR_INV_HCI_CMD_PARMS; + if (handle <= BLE_LL_CONN_MAX_CONN_HANDLE) { + /* Make sure reason is valid */ + switch (cmd->reason) { + case BLE_ERR_AUTH_FAIL: + case BLE_ERR_REM_USER_CONN_TERM: + case BLE_ERR_RD_CONN_TERM_RESRCS: + case BLE_ERR_RD_CONN_TERM_PWROFF: + case BLE_ERR_UNSUPP_REM_FEATURE: + case BLE_ERR_UNIT_KEY_PAIRING: + case BLE_ERR_CONN_PARMS: + connsm = ble_ll_conn_find_active_conn(handle); + if (connsm) { + /* Do not allow command if we are in process of disconnecting */ + if (connsm->disconnect_reason) { + rc = BLE_ERR_CMD_DISALLOWED; + } else { + /* This control procedure better not be pending! */ + BLE_LL_ASSERT(CONN_F_TERMINATE_STARTED(connsm) == 0); + + /* Record the disconnect reason */ + connsm->disconnect_reason = cmd->reason; + + /* Start this control procedure */ + ble_ll_ctrl_terminate_start(connsm); + + rc = BLE_ERR_SUCCESS; + } + } else { + rc = BLE_ERR_UNK_CONN_ID; + } + break; + default: + break; + } + } + + return rc; +} + +/** + * Called to process a HCI disconnect command + * + * Context: Link Layer task (HCI command parser). + * + * @param cmdbuf + * + * @return int + */ +int +ble_ll_conn_hci_rd_rem_ver_cmd(const uint8_t *cmdbuf, uint8_t len) +{ + struct ble_ll_conn_sm *connsm; + const struct ble_hci_rd_rem_ver_info_cp *cmd = (const void *) cmdbuf; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Check for valid parameters */ + connsm = ble_ll_conn_find_active_conn(le16toh(cmd->conn_handle)); + if (!connsm) { + return BLE_ERR_UNK_CONN_ID; + } + + /* Return error if in progress */ + if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_VERSION_XCHG)) { + return BLE_ERR_CMD_DISALLOWED; + } + + /* + * Start this control procedure. If we have already done this control + * procedure we set the pending bit so that the host gets an event because + * it is obviously expecting one (or would not have sent the command). + * NOTE: we cant just send the event here. That would cause the event to + * be queued before the command status. + */ + if (!connsm->csmflags.cfbit.version_ind_sent) { + ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_VERSION_XCHG); + } else { + connsm->pending_ctrl_procs |= (1 << BLE_LL_CTRL_PROC_VERSION_XCHG); + } + + return BLE_ERR_SUCCESS; +} + +/** + * Called to read the RSSI for a given connection handle + * + * @param cmdbuf + * @param rspbuf + * @param rsplen + * + * @return int + */ +int +ble_ll_conn_hci_rd_rssi(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen) +{ + + const struct ble_hci_rd_rssi_cp *cmd = (const void *) cmdbuf; + struct ble_hci_rd_rssi_rp *rsp = (void *) rspbuf; + struct ble_ll_conn_sm *connsm; + int rc; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + rsp->handle = cmd->handle; + + connsm = ble_ll_conn_find_active_conn(le16toh(cmd->handle)); + if (!connsm) { + rsp->rssi = 127; + rc = BLE_ERR_UNK_CONN_ID; + } else { + rsp->rssi = connsm->conn_rssi; + rc = BLE_ERR_SUCCESS; + } + + *rsplen = sizeof(*rsp); + return rc; +} + +/** + * Called to read the current channel map of a connection + * + * @param cmdbuf + * @param rspbuf + * @param rsplen + * + * @return int + */ +int +ble_ll_conn_hci_rd_chan_map(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_le_rd_chan_map_cp *cmd = (const void *) cmdbuf; + struct ble_hci_le_rd_chan_map_rp *rsp = (void *) rspbuf; + struct ble_ll_conn_sm *connsm; + uint16_t handle; + int rc; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + handle = le16toh(cmd->conn_handle); + connsm = ble_ll_conn_find_active_conn(handle); + if (!connsm) { + rc = BLE_ERR_UNK_CONN_ID; + memset(rsp->chan_map, 0, sizeof(rsp->chan_map)); + } else { + if (connsm->csmflags.cfbit.chanmap_update_scheduled) { + memcpy(rsp->chan_map, connsm->req_chanmap, BLE_LL_CONN_CHMAP_LEN); + } else { + memcpy(rsp->chan_map, connsm->chanmap, BLE_LL_CONN_CHMAP_LEN); + } + rc = BLE_ERR_SUCCESS; + } + + rsp->conn_handle = htole16(handle); + + *rsplen = sizeof(*rsp); + return rc; +} + +/** + * Called when the host issues the LE command "set host channel classification" + * + * @param cmdbuf + * + * @return int + */ +int +ble_ll_conn_hci_set_chan_class(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_set_host_chan_class_cp *cmd = (const void *) cmdbuf; + uint8_t num_used_chans; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* + * The HCI command states that the host is allowed to mask in just one + * channel but the Link Layer needs minimum two channels to operate. So + * I will not allow this command if there are less than 2 channels masked. + */ + num_used_chans = ble_ll_utils_calc_num_used_chans(cmd->chan_map); + if ((num_used_chans < 2) || ((cmd->chan_map[4] & 0xe0) != 0)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Set the host channel mask */ + ble_ll_conn_set_global_chanmap(num_used_chans, cmd->chan_map); + return BLE_ERR_SUCCESS; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) +int +ble_ll_conn_hci_set_data_len(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_le_set_data_len_cp *cmd = (const void *) cmdbuf; + struct ble_hci_le_set_data_len_rp *rsp = (void *) rspbuf; + int rc; + uint16_t handle; + uint16_t txoctets; + uint16_t txtime; + struct ble_ll_conn_sm *connsm; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Find connection */ + handle = le16toh(cmd->conn_handle); + connsm = ble_ll_conn_find_active_conn(handle); + if (!connsm) { + rc = BLE_ERR_UNK_CONN_ID; + goto done; + } + + txoctets = le16toh(cmd->tx_octets); + txtime = le16toh(cmd->tx_time); + + /* Make sure it is valid */ + if (!ble_ll_chk_txrx_octets(txoctets) || + !ble_ll_chk_txrx_time(txtime)) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + /* + * Keep original value requested by host since we may want to recalculate + * MaxTxTime after PHY changes between coded and uncoded. + */ + connsm->host_req_max_tx_time = txtime; + + /* If peer does not support coded, we cannot use value larger than 2120us */ + if (!(connsm->remote_features[0] & (BLE_LL_FEAT_LE_CODED_PHY >> 8))) { + txtime = min(txtime, BLE_LL_CONN_SUPP_TIME_MAX_UNCODED); + } +#endif + + rc = BLE_ERR_SUCCESS; + if (connsm->max_tx_time != txtime || + connsm->max_tx_octets != txoctets) { + + connsm->max_tx_time = txtime; + connsm->max_tx_octets = txoctets; + + ble_ll_ctrl_initiate_dle(connsm); + } + +done: + rsp->conn_handle = htole16(handle); + *rsplen = sizeof(*rsp); + return rc; +} +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) +/** + * LE start encrypt command + * + * @param cmdbuf + * + * @return int + */ +int +ble_ll_conn_hci_le_start_encrypt(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_start_encrypt_cp *cmd = (const void *) cmdbuf; + struct ble_ll_conn_sm *connsm; + int rc; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + connsm = ble_ll_conn_find_active_conn(le16toh(cmd->conn_handle)); + if (!connsm) { + rc = BLE_ERR_UNK_CONN_ID; + } else if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { + rc = BLE_ERR_UNSPECIFIED; + } else if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_ENCRYPT) { + /* + * The specification does not say what to do here but the host should + * not be telling us to start encryption while we are in the process + * of honoring a previous start encrypt. + */ + rc = BLE_ERR_CMD_DISALLOWED; + } else { + /* Start the control procedure */ + connsm->enc_data.host_rand_num = le64toh(cmd->rand); + connsm->enc_data.enc_div = le16toh(cmd->div); + swap_buf(connsm->enc_data.enc_block.key, cmd->ltk, 16); + ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_ENCRYPT); + rc = BLE_ERR_SUCCESS; + } + + return rc; +} + +/** + * Called to process the LE long term key reply. + * + * Context: Link Layer Task. + * + * @param cmdbuf + * @param rspbuf + * @param ocf + * + * @return int + */ +int +ble_ll_conn_hci_le_ltk_reply(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_le_lt_key_req_reply_cp *cmd = (const void *) cmdbuf; + struct ble_hci_le_lt_key_req_reply_rp *rsp = (void *) rspbuf; + struct ble_ll_conn_sm *connsm; + uint16_t handle; + int rc; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Find connection handle */ + handle = le16toh(cmd->conn_handle); + connsm = ble_ll_conn_find_active_conn(handle); + if (!connsm) { + rc = BLE_ERR_UNK_CONN_ID; + goto ltk_key_cmd_complete; + } + + /* Should never get this if we are a master! */ + if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + rc = BLE_ERR_UNSPECIFIED; + goto ltk_key_cmd_complete; + } + + /* The connection should be awaiting a reply. If not, just discard */ + if (connsm->enc_data.enc_state != CONN_ENC_S_LTK_REQ_WAIT) { + rc = BLE_ERR_CMD_DISALLOWED; + goto ltk_key_cmd_complete; + } + + swap_buf(connsm->enc_data.enc_block.key, cmd->ltk, 16); + ble_ll_calc_session_key(connsm); + ble_ll_ctrl_start_enc_send(connsm); + rc = BLE_ERR_SUCCESS; + +ltk_key_cmd_complete: + rsp->conn_handle = htole16(handle); + + *rsplen = sizeof(*rsp); + return rc; +} + +/** + * Called to process the LE long term key negative reply. + * + * Context: Link Layer Task. + * + * @param cmdbuf + * @param rspbuf + * @param ocf + * + * @return int + */ +int +ble_ll_conn_hci_le_ltk_neg_reply(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_le_lt_key_req_neg_reply_cp *cmd = (const void *) cmdbuf; + struct ble_hci_le_lt_key_req_neg_reply_rp *rsp = (void *) rspbuf; + struct ble_ll_conn_sm *connsm; + uint16_t handle; + int rc; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Find connection handle */ + handle = le16toh(cmd->conn_handle); + connsm = ble_ll_conn_find_active_conn(handle); + if (!connsm) { + rc = BLE_ERR_UNK_CONN_ID; + goto ltk_key_cmd_complete; + } + + /* Should never get this if we are a master! */ + if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + rc = BLE_ERR_UNSPECIFIED; + goto ltk_key_cmd_complete; + } + + /* The connection should be awaiting a reply. If not, just discard */ + if (connsm->enc_data.enc_state != CONN_ENC_S_LTK_REQ_WAIT) { + rc = BLE_ERR_CMD_DISALLOWED; + goto ltk_key_cmd_complete; + } + + /* We received a negative reply! Send REJECT_IND */ + ble_ll_ctrl_reject_ind_send(connsm, BLE_LL_CTRL_ENC_REQ, + BLE_ERR_PINKEY_MISSING); + connsm->enc_data.enc_state = CONN_ENC_S_LTK_NEG_REPLY; + + rc = BLE_ERR_SUCCESS; + +ltk_key_cmd_complete: + rsp->conn_handle = htole16(handle); + + *rsplen = sizeof(*rsp); + return rc; +} +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) +/** + * Read authenticated payload timeout (OGF=3, OCF==0x007B) + * + * @param cmdbuf + * @param rsplen + * + * @return int + */ +int +ble_ll_conn_hci_rd_auth_pyld_tmo(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_cb_rd_auth_pyld_tmo_cp *cmd = (const void *) cmdbuf; + struct ble_hci_cb_rd_auth_pyld_tmo_rp *rsp = (void *) rspbuf; + struct ble_ll_conn_sm *connsm; + uint16_t handle; + int rc; + + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + handle = le16toh(cmd->conn_handle); + connsm = ble_ll_conn_find_active_conn(handle); + if (!connsm) { + rc = BLE_ERR_UNK_CONN_ID; + rsp->tmo = 0; + } else { + rc = BLE_ERR_SUCCESS; + rsp->tmo = htole16(connsm->auth_pyld_tmo); + } + + rsp->conn_handle = htole16(handle); + + *rsplen = sizeof(*rsp); + return rc; +} + +/** + * Write authenticated payload timeout (OGF=3, OCF=00x7C) + * + * @param cmdbuf + * @param rsplen + * + * @return int + */ +int +ble_ll_conn_hci_wr_auth_pyld_tmo(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_cb_wr_auth_pyld_tmo_cp *cmd = (const void *) cmdbuf; + struct ble_hci_cb_wr_auth_pyld_tmo_rp *rsp = (void *) rspbuf; + struct ble_ll_conn_sm *connsm; + uint32_t min_tmo; + uint16_t handle; + uint16_t tmo; + int rc; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + rc = BLE_ERR_SUCCESS; + + handle = le16toh(cmd->conn_handle); + + connsm = ble_ll_conn_find_active_conn(handle); + if (!connsm) { + rc = BLE_ERR_UNK_CONN_ID; + } else { + /* + * The timeout is in units of 10 msecs. We need to make sure that the + * timeout is greater than or equal to connItvl * (1 + slaveLatency) + */ + tmo = le16toh(cmd->tmo); + min_tmo = (uint32_t)connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS; + min_tmo *= (connsm->slave_latency + 1); + min_tmo /= 10000; + + if (tmo < min_tmo) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + } else { + connsm->auth_pyld_tmo = tmo; + if (ble_npl_callout_is_active(&connsm->auth_pyld_timer)) { + ble_ll_conn_auth_pyld_timer_start(connsm); + } + } + } + + rsp->conn_handle = htole16(handle); + *rsplen = sizeof(*rsp); + return rc; +} +#endif + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +/** + * Read current phy for connection (OGF=8, OCF==0x0030) + * + * @param cmdbuf + * @param rsplen + * + * @return int + */ +int +ble_ll_conn_hci_le_rd_phy(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_le_rd_phy_cp *cmd = (const void *) cmdbuf; + struct ble_hci_le_rd_phy_rp *rsp = (void *) rspbuf; + int rc; + uint16_t handle; + struct ble_ll_conn_sm *connsm; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + handle = le16toh(cmd->conn_handle); + connsm = ble_ll_conn_find_active_conn(handle); + if (!connsm) { + rsp->tx_phy = 0; + rsp->rx_phy = 0; + rc = BLE_ERR_UNK_CONN_ID; + } else { + rsp->tx_phy = connsm->phy_data.cur_tx_phy; + rsp->rx_phy = connsm->phy_data.cur_rx_phy; + rc = BLE_ERR_SUCCESS; + } + + rsp->conn_handle = htole16(handle); + + *rsplen = sizeof(*rsp); + return rc; +} + +/** + * Set PHY preferences for connection + * + * @param cmdbuf + * + * @return int + */ +int +ble_ll_conn_hci_le_set_phy(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_set_phy_cp *cmd = (const void *) cmdbuf; + int rc; + uint16_t phy_options; + uint8_t tx_phys; + uint8_t rx_phys; + uint16_t handle; + struct ble_ll_conn_sm *connsm; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + handle = le16toh(cmd->conn_handle); + connsm = ble_ll_conn_find_active_conn(handle); + if (!connsm) { + return BLE_ERR_UNK_CONN_ID; + } + + /* + * If host has requested a PHY update and we are not finished do + * not allow another one + */ + if (CONN_F_HOST_PHY_UPDATE(connsm)) { + return BLE_ERR_CMD_DISALLOWED; + } + + phy_options = le16toh(cmd->phy_options); + if (phy_options > BLE_HCI_LE_PHY_CODED_S8_PREF) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Check valid parameters */ + rc = ble_ll_hci_chk_phy_masks(cmd->all_phys, cmd->tx_phys, cmd->rx_phys, + &tx_phys, &rx_phys); + if (rc) { + goto phy_cmd_param_err; + } + + connsm->phy_data.phy_options = phy_options & 0x03; + connsm->phy_data.host_pref_tx_phys_mask = tx_phys, + connsm->phy_data.host_pref_rx_phys_mask = rx_phys; + + /* + * The host preferences override the default phy preferences. Currently, + * the only reason the controller will initiate a procedure on its own + * is due to the fact that the host set default preferences. So if there + * is a pending control procedure and it has not yet started, we do not + * need to perform the default controller procedure. + */ + if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE)) { + if (connsm->cur_ctrl_proc != BLE_LL_CTRL_PROC_PHY_UPDATE) { + CONN_F_CTRLR_PHY_UPDATE(connsm) = 0; + } + CONN_F_HOST_PHY_UPDATE(connsm) = 1; + } else { + /* + * We could be doing a peer-initiated PHY update procedure. If this + * is the case the requested phy preferences will not both be 0. If + * we are not done with a peer-initiated procedure we just set the + * pending bit but do not start the control procedure. + */ + if (CONN_F_PEER_PHY_UPDATE(connsm)) { + connsm->pending_ctrl_procs |= (1 << BLE_LL_CTRL_PROC_PHY_UPDATE); + CONN_F_HOST_PHY_UPDATE(connsm) = 1; + } else { + /* Check if we should start phy update procedure */ + if (!ble_ll_conn_chk_phy_upd_start(connsm)) { + CONN_F_HOST_PHY_UPDATE(connsm) = 1; + } else { + /* + * Set flag to send a PHY update complete event. We set flag + * even if we do not do an update procedure since we have to + * inform the host even if we decide not to change anything. + */ + CONN_F_PHY_UPDATE_EVENT(connsm) = 1; + } + } + } + +phy_cmd_param_err: + return rc; +} +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) +int +ble_ll_set_sync_transfer_params(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_le_periodic_adv_sync_transfer_params_cp *cmd = (const void *)cmdbuf; + struct ble_hci_le_periodic_adv_sync_transfer_params_rp *rsp = (void *) rspbuf; + struct ble_ll_conn_sm *connsm; + uint16_t sync_timeout; + uint16_t skip; + int rc; + + if (len != sizeof(*cmd)) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + + if (cmd->mode > 0x02) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + + skip = le16toh(cmd->skip); + if (skip > 0x01f3) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + + sync_timeout = le16toh(cmd->sync_timeout); + if ((sync_timeout < 0x000a) || (sync_timeout > 0x4000)) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + + /* we don't support any CTE yet */ + if (cmd->sync_cte_type) { + rc = BLE_ERR_UNSUPPORTED; + goto done; + } + + connsm = ble_ll_conn_find_active_conn(le16toh(cmd->conn_handle)); + if (!connsm) { + rc = BLE_ERR_UNK_CONN_ID; + goto done; + } + + /* timeout in 10ms units */ + connsm->sync_transfer_sync_timeout = sync_timeout * 10000; + connsm->sync_transfer_mode = cmd->mode; + connsm->sync_transfer_skip = skip; + + rc = BLE_ERR_SUCCESS; + +done: + rsp->conn_handle = cmd->conn_handle; + *rsplen = sizeof(*rsp); + return rc; +} + +int +ble_ll_set_default_sync_transfer_params(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_set_default_periodic_sync_transfer_params_cp *cmd = (const void *)cmdbuf; + uint16_t sync_timeout; + uint16_t skip; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (cmd->mode > 0x02) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + skip = le16toh(cmd->skip); + if (skip > 0x01f3) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + sync_timeout = le16toh(cmd->sync_timeout); + if ((sync_timeout < 0x000a) || (sync_timeout > 0x4000)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* we don't support any CTE yet */ + if (cmd->sync_cte_type) { + return BLE_ERR_UNSUPPORTED; + } + + /* timeout in 10ms units */ + g_ble_ll_conn_sync_transfer_params.sync_timeout_us = sync_timeout * 10000; + g_ble_ll_conn_sync_transfer_params.mode = cmd->mode; + g_ble_ll_conn_sync_transfer_params.max_skip = skip; + + return BLE_ERR_SUCCESS; +} +#endif +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn_priv.h new file mode 100644 index 000000000..e4ade10f9 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn_priv.h @@ -0,0 +1,226 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_LL_CONN_PRIV_ +#define H_BLE_LL_CONN_PRIV_ + +#include "../include/controller/ble_ll_conn.h" +#include "../include/controller/ble_ll_hci.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Definitions for min/max RX/TX time/bytes values allowed for connections. + * Source: Core 5.0 specification, Vol 6, Part B, section 4.5.10 + */ +#define BLE_LL_CONN_SUPP_TIME_MIN (328) /* usecs */ +#define BLE_LL_CONN_SUPP_TIME_MAX (17040) /* usecs */ +#define BLE_LL_CONN_SUPP_TIME_MIN_UNCODED (328) /* usecs */ +#define BLE_LL_CONN_SUPP_TIME_MAX_UNCODED (2120) /* usecs */ +#define BLE_LL_CONN_SUPP_TIME_MIN_CODED (2704) /* usecs */ +#define BLE_LL_CONN_SUPP_TIME_MAX_CODED (17040) /* usecs */ +#define BLE_LL_CONN_SUPP_BYTES_MIN (27) /* bytes */ +#define BLE_LL_CONN_SUPP_BYTES_MAX (251) /* bytes */ + +/* Connection event timing */ +#define BLE_LL_CONN_INITIAL_OFFSET (1250) +#define BLE_LL_CONN_ITVL_USECS (1250) +#define BLE_LL_CONN_TX_WIN_USECS (1250) +#define BLE_LL_CONN_TX_OFF_USECS (1250) +#define BLE_LL_CONN_CE_USECS (625) +#define BLE_LL_CONN_TX_WIN_MIN (1) /* in tx win units */ +#define BLE_LL_CONN_SLAVE_LATENCY_MAX (499) + +/* Connection handle range */ +#define BLE_LL_CONN_MAX_CONN_HANDLE (0x0EFF) + +/* Offset (in bytes) of advertising address in connect request */ +#define BLE_LL_CONN_REQ_ADVA_OFF (BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN) + +/* Default authenticated payload timeout (30 seconds; in 10 msecs increments) */ +#define BLE_LL_CONN_DEF_AUTH_PYLD_TMO (3000) +#define BLE_LL_CONN_AUTH_PYLD_OS_TMO(x) ble_npl_time_ms_to_ticks32((x) * 10) + +/* Global Link Layer connection parameters */ +struct ble_ll_conn_global_params +{ + uint8_t master_chan_map[BLE_LL_CONN_CHMAP_LEN]; + uint8_t num_used_chans; + uint8_t supp_max_tx_octets; + uint8_t supp_max_rx_octets; + uint8_t conn_init_max_tx_octets; + uint8_t sugg_tx_octets; + uint16_t sugg_tx_time; + uint16_t conn_init_max_tx_time; + uint16_t conn_init_max_tx_time_uncoded; + uint16_t conn_init_max_tx_time_coded; + uint16_t supp_max_tx_time; + uint16_t supp_max_rx_time; +}; +extern struct ble_ll_conn_global_params g_ble_ll_conn_params; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) +struct ble_ll_conn_sync_transfer_params +{ + uint32_t sync_timeout_us; + uint16_t max_skip; + uint8_t mode; +}; +extern struct ble_ll_conn_sync_transfer_params g_ble_ll_conn_sync_transfer_params; +#endif + +/* Some data structures used by other LL routines */ +SLIST_HEAD(ble_ll_conn_active_list, ble_ll_conn_sm); +STAILQ_HEAD(ble_ll_conn_free_list, ble_ll_conn_sm); +extern struct ble_ll_conn_active_list g_ble_ll_conn_active_list; +extern struct ble_ll_conn_free_list g_ble_ll_conn_free_list; + +/* Pointer to connection state machine we are trying to create */ +extern struct ble_ll_conn_sm *g_ble_ll_conn_create_sm; + +/* Generic interface */ +struct ble_ll_len_req; +struct ble_mbuf_hdr; +struct ble_ll_adv_sm; + +struct hci_create_conn +{ + uint16_t scan_itvl; + uint16_t scan_window; + uint8_t filter_policy; + uint8_t peer_addr_type; + uint8_t peer_addr[BLE_DEV_ADDR_LEN]; + uint8_t own_addr_type; + uint16_t conn_itvl_min; + uint16_t conn_itvl_max; + uint16_t conn_latency; + uint16_t supervision_timeout; + uint16_t min_ce_len; + uint16_t max_ce_len; +}; + +void ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm); +void ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err); +void ble_ll_conn_enqueue_pkt(struct ble_ll_conn_sm *connsm, struct os_mbuf *om, + uint8_t hdr_byte, uint8_t length); +struct ble_ll_conn_sm *ble_ll_conn_sm_get(void); +void ble_ll_conn_master_init(struct ble_ll_conn_sm *connsm, + struct hci_create_conn *hcc); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +void ble_ll_conn_ext_master_init(struct ble_ll_conn_sm *connsm, + struct hci_ext_create_conn *hcc); + +void ble_ll_conn_ext_set_params(struct ble_ll_conn_sm *connsm, + struct hci_ext_conn_params *hcc_params, + int phy); +#endif + +struct ble_ll_conn_sm *ble_ll_conn_find_active_conn(uint16_t handle); +void ble_ll_conn_update_eff_data_len(struct ble_ll_conn_sm *connsm); + +/* Advertising interface */ +int ble_ll_conn_slave_start(uint8_t *rxbuf, uint8_t pat, + struct ble_mbuf_hdr *rxhdr, bool force_csa2); + +/* Link Layer interface */ +void ble_ll_conn_module_init(void); +void ble_ll_conn_set_global_chanmap(uint8_t num_used_chans, const uint8_t *chanmap); +void ble_ll_conn_module_reset(void); +void ble_ll_conn_tx_pkt_in(struct os_mbuf *om, uint16_t handle, uint16_t len); +int ble_ll_conn_rx_isr_start(struct ble_mbuf_hdr *rxhdr, uint32_t aa); +int ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr); +void ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr); +void ble_ll_init_rx_pkt_in(uint8_t pdu_type, uint8_t *rxbuf, + struct ble_mbuf_hdr *ble_hdr); +int ble_ll_init_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *ble_hdr); +int ble_ll_init_rx_isr_end(uint8_t *rxbuf, uint8_t crcok, + struct ble_mbuf_hdr *ble_hdr); +void ble_ll_conn_wfr_timer_exp(void); +void ble_ll_conn_init_wfr_timer_exp(void); +int ble_ll_conn_is_lru(struct ble_ll_conn_sm *s1, struct ble_ll_conn_sm *s2); +uint32_t ble_ll_conn_get_ce_end_time(void); +void ble_ll_conn_event_halt(void); +void ble_ll_conn_reset_pending_aux_conn_rsp(void); +bool ble_ll_conn_init_pending_aux_conn_rsp(void); +/* HCI */ +void ble_ll_disconn_comp_event_send(struct ble_ll_conn_sm *connsm, + uint8_t reason); +void ble_ll_auth_pyld_tmo_event_send(struct ble_ll_conn_sm *connsm); +int ble_ll_conn_hci_disconnect_cmd(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_conn_hci_rd_rem_ver_cmd(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_conn_hci_set_chan_class(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_conn_hci_param_rr(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen); +int ble_ll_conn_hci_param_nrr(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen); +int ble_ll_conn_create_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb); +void ble_ll_conn_num_comp_pkts_event_send(struct ble_ll_conn_sm *connsm); +void ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status, + uint8_t *evbuf, struct ble_ll_adv_sm *advsm); +void ble_ll_conn_timeout(struct ble_ll_conn_sm *connsm, uint8_t ble_err); +int ble_ll_conn_hci_chk_conn_params(uint16_t itvl_min, uint16_t itvl_max, + uint16_t latency, uint16_t spvn_tmo); +int ble_ll_conn_hci_read_rem_features(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_conn_hci_rd_rssi(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, + uint8_t *rsplen); +int ble_ll_conn_hci_rd_chan_map(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen); +int ble_ll_conn_hci_set_data_len(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen); +int ble_ll_conn_hci_le_start_encrypt(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_conn_hci_le_ltk_reply(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen); +int ble_ll_conn_hci_le_ltk_neg_reply(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen); +int ble_ll_conn_hci_wr_auth_pyld_tmo(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen); +int ble_ll_conn_hci_rd_auth_pyld_tmo(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) +void ble_ll_conn_auth_pyld_timer_start(struct ble_ll_conn_sm *connsm); +#else +#define ble_ll_conn_auth_pyld_timer_start(x) +#endif + +int ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg); +int ble_ll_hci_acl_rx(struct os_mbuf *om, void *arg); + +int ble_ll_conn_hci_le_rd_phy(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rsp, uint8_t *rsplen); +int ble_ll_conn_hci_le_set_phy(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_conn_chk_phy_upd_start(struct ble_ll_conn_sm *connsm); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +int ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t cmdlen); +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) +int ble_ll_set_sync_transfer_params(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen); +int ble_ll_set_default_sync_transfer_params(const uint8_t *cmdbuf, uint8_t len); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* H_BLE_LL_CONN_PRIV_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_ctrl.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_ctrl.c new file mode 100644 index 000000000..1d5ed929b --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_ctrl.c @@ -0,0 +1,2747 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef ESP_PLATFORM + +#include +#include +#include +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/include/nimble/nimble_opt.h" +#include "nimble/nimble/include/nimble/hci_common.h" +#include "../include/controller/ble_ll.h" +#include "../include/controller/ble_ll_hci.h" +#include "../include/controller/ble_ll_ctrl.h" +#include "../include/controller/ble_ll_trace.h" +#include "../include/controller/ble_hw.h" +#include "../include/controller/ble_ll_sync.h" +#include "ble_ll_conn_priv.h" + +/* To use spec sample data for testing */ +#undef BLE_LL_ENCRYPT_USE_TEST_DATA + +/* + * For console debug to show session key calculation. NOTE: if you define + * this the stack requirements for the LL task go up considerably. The + * default stack will not be enough and must be increased. + */ +#undef BLE_LL_ENCRYPT_DEBUG +#ifdef BLE_LL_ENCRYPT_DEBUG +#include "console/console.h" +#endif + +/* + * XXX: + * 1) Do I need to keep track of which procedures have already been done? + * Do I need to worry about repeating procedures? + * 2) Should we create pool of control pdu's?. Dont need more + * than the # of connections and can probably deal with quite a few less + * if we have lots of connections. + * 3) What about procedures that have been completed but try to restart? + * 4) NOTE: there is a supported features procedure. However, in the case + * of data length extension, if the receiving device does not understand + * the pdu or it does not support data length extension, the LL_UNKNOWN_RSP + * pdu is sent. That needs to be processed... + * 5) We are supposed to remember when we do the data length update proc if + * the device sent us an unknown rsp. We should not send it another len req. + * Implement this how? Through remote supported features? + * 8) How to count control pdus sent. DO we count enqueued + sent, or only + * sent (actually attempted to tx). Do we count failures? How? + */ + +/* + * XXX: I definitely have an issue with control procedures and connection + * param request procedure and connection update procedure. This was + * noted when receiving an unknown response. Right now, I am getting confused + * with connection parameter request and updates regarding which procedures + * are running. So I need to go look through all the code and see where I + * used the request procedure and the update procedure and make sure I am doing + * the correct thing. + */ + +/* + * This array contains the length of the CtrData field in LL control PDU's. + * Note that there is a one byte opcode which precedes this field in the LL + * control PDU, so total data channel payload length for the control pdu is + * one greater. + */ +const uint8_t g_ble_ll_ctrl_pkt_lengths[BLE_LL_CTRL_OPCODES] = +{ + BLE_LL_CTRL_CONN_UPD_REQ_LEN, + BLE_LL_CTRL_CHAN_MAP_LEN, + BLE_LL_CTRL_TERMINATE_IND_LEN, + BLE_LL_CTRL_ENC_REQ_LEN, + BLE_LL_CTRL_ENC_RSP_LEN, + BLE_LL_CTRL_START_ENC_REQ_LEN, + BLE_LL_CTRL_START_ENC_RSP_LEN, + BLE_LL_CTRL_UNK_RSP_LEN, + BLE_LL_CTRL_FEATURE_LEN, + BLE_LL_CTRL_FEATURE_LEN, + BLE_LL_CTRL_PAUSE_ENC_REQ_LEN, + BLE_LL_CTRL_PAUSE_ENC_RSP_LEN, + BLE_LL_CTRL_VERSION_IND_LEN, + BLE_LL_CTRL_REJ_IND_LEN, + BLE_LL_CTRL_SLAVE_FEATURE_REQ_LEN, + BLE_LL_CTRL_CONN_PARAMS_LEN, + BLE_LL_CTRL_CONN_PARAMS_LEN, + BLE_LL_CTRL_REJECT_IND_EXT_LEN, + BLE_LL_CTRL_PING_LEN, + BLE_LL_CTRL_PING_LEN, + BLE_LL_CTRL_LENGTH_REQ_LEN, + BLE_LL_CTRL_LENGTH_REQ_LEN, + BLE_LL_CTRL_PHY_REQ_LEN, + BLE_LL_CTRL_PHY_RSP_LEN, + BLE_LL_CTRL_PHY_UPD_IND_LEN, + BLE_LL_CTRL_MIN_USED_CHAN_LEN, + BLE_LL_CTRL_CTE_REQ_LEN, + BLE_LL_CTRL_CTE_RSP_LEN, + BLE_LL_CTRL_PERIODIC_SYNC_IND_LEN, + BLE_LL_CTRL_CLOCK_ACCURACY_REQ_LEN, + BLE_LL_CTRL_CLOCK_ACCURACY_RSP_LEN, +}; + +/** + * Called to determine if a LL control procedure with an instant has + * been initiated. + * + * If the function returns a 0 it means no conflicting procedure has + * been initiated. Otherwise it returns the appropriate BLE error code to + * send. + * + * @param connsm Pointer to connection state machine. + * @param req_ctrl_proc The procedure that the peer is trying to initiate + * + * @return uint8_t + */ +uint8_t +ble_ll_ctrl_proc_with_instant_initiated(struct ble_ll_conn_sm *connsm, + uint8_t req_ctrl_proc) +{ + uint8_t err; + + switch (connsm->cur_ctrl_proc) { + case BLE_LL_CTRL_PROC_PHY_UPDATE: + case BLE_LL_CTRL_PROC_CONN_UPDATE: + case BLE_LL_CTRL_PROC_CONN_PARAM_REQ: + case BLE_LL_CTRL_PROC_CHAN_MAP_UPD: + if (req_ctrl_proc == connsm->cur_ctrl_proc) { + err = BLE_ERR_LMP_COLLISION; + } else if ((connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_CONN_UPDATE) && + (req_ctrl_proc == BLE_LL_CTRL_PROC_CONN_PARAM_REQ)) { + err = BLE_ERR_LMP_COLLISION; + } else { + err = BLE_ERR_DIFF_TRANS_COLL; + } + break; + default: + err = 0; + } + + return err; +} + +/** + * Create a LL_REJECT_EXT_IND pdu. + * + * @param rej_opcode Opcode to be rejected. + * @param err: error response + * @param ctrdata: Pointer to where CtrData starts in pdu + */ +void +ble_ll_ctrl_rej_ext_ind_make(uint8_t rej_opcode, uint8_t err, uint8_t *ctrdata) +{ + ctrdata[0] = rej_opcode; + ctrdata[1] = err; +} + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +/** + * Called to cancel a phy update procedure. + * + * @param connsm + * @param ble_err + */ +void +ble_ll_ctrl_phy_update_cancel(struct ble_ll_conn_sm *connsm, uint8_t ble_err) +{ + /* cancel any pending phy update procedures */ + CLR_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE); + + /* Check if the host wants an event */ + if (CONN_F_HOST_PHY_UPDATE(connsm)) { + ble_ll_hci_ev_phy_update(connsm, ble_err); + CONN_F_HOST_PHY_UPDATE(connsm) = 0; + } + + /* Clear any bits for phy updates that might be in progress */ + CONN_F_CTRLR_PHY_UPDATE(connsm) = 0; +} +#endif + +static int +ble_ll_ctrl_len_proc(struct ble_ll_conn_sm *connsm, uint8_t *dptr) +{ + int rc; + struct ble_ll_len_req ctrl_req; + + /* Extract parameters and check if valid */ + ctrl_req.max_rx_bytes = get_le16(dptr); + ctrl_req.max_rx_time = get_le16(dptr + 2); + ctrl_req.max_tx_bytes = get_le16(dptr + 4); + ctrl_req.max_tx_time = get_le16(dptr + 6); + + if ((ctrl_req.max_rx_bytes < BLE_LL_CONN_SUPP_BYTES_MIN) || + (ctrl_req.max_rx_time < BLE_LL_CONN_SUPP_TIME_MIN) || + (ctrl_req.max_tx_bytes < BLE_LL_CONN_SUPP_BYTES_MIN) || + (ctrl_req.max_tx_time < BLE_LL_CONN_SUPP_TIME_MIN)) { + rc = 1; + } else { + /* Update parameters */ + connsm->rem_max_rx_time = ctrl_req.max_rx_time; + connsm->rem_max_tx_time = ctrl_req.max_tx_time; + connsm->rem_max_rx_octets = ctrl_req.max_rx_bytes; + connsm->rem_max_tx_octets = ctrl_req.max_tx_bytes; + + /* Recalculate effective connection parameters */ + ble_ll_conn_update_eff_data_len(connsm); + rc = 0; + } + + return rc; +} + +/** + * Process a received LL_PING_RSP control pdu. + * + * NOTE: we dont have to reset the callout since this packet will have had a + * valid MIC and that will restart the authenticated payload timer + * + * @param connsm + */ +static void +ble_ll_ctrl_rx_ping_rsp(struct ble_ll_conn_sm *connsm) +{ + /* Stop the control procedure */ + ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_LE_PING); +} + +/** + * Called when we receive either a connection parameter request or response. + * + * @param connsm + * @param dptr + * @param rspbuf + * @param opcode + * + * @return int + */ +static int +ble_ll_ctrl_conn_param_pdu_proc(struct ble_ll_conn_sm *connsm, uint8_t *dptr, + uint8_t *rspbuf, uint8_t opcode) +{ + int rc; + int indicate; + uint8_t rsp_opcode; + uint8_t ble_err; + struct ble_ll_conn_params *req; + struct hci_conn_update *hcu; + + /* Extract parameters and check if valid */ + req = &connsm->conn_cp; + req->interval_min = get_le16(dptr); + req->interval_max = get_le16(dptr + 2); + req->latency = get_le16(dptr + 4); + req->timeout = get_le16(dptr + 6); + req->pref_periodicity = dptr[8]; + req->ref_conn_event_cnt = get_le16(dptr + 9); + req->offset0 = get_le16(dptr + 11); + req->offset1 = get_le16(dptr + 13); + req->offset2 = get_le16(dptr + 15); + req->offset3 = get_le16(dptr + 17); + req->offset4 = get_le16(dptr + 19); + req->offset5 = get_le16(dptr + 21); + + /* Check if parameters are valid */ + ble_err = BLE_ERR_SUCCESS; + rc = ble_ll_conn_hci_chk_conn_params(req->interval_min, + req->interval_max, + req->latency, + req->timeout); + if (rc) { + ble_err = BLE_ERR_INV_LMP_LL_PARM; + goto conn_param_pdu_exit; + } + + /* + * Check if there is a requested change to either the interval, timeout + * or latency. If not, this may just be an anchor point change and we do + * not have to notify the host. + * XXX: what if we dont like the parameters? When do we check that out? + */ + indicate = 1; + if (opcode == BLE_LL_CTRL_CONN_PARM_REQ) { + if ((connsm->conn_itvl >= req->interval_min) && + (connsm->conn_itvl <= req->interval_max) && + (connsm->supervision_tmo == req->timeout) && + (connsm->slave_latency == req->latency)) { + indicate = 0; + goto conn_parm_req_do_indicate; + } + } + + /* + * A change has been requested. Is it within the values specified by + * the host? Note that for a master we will not be processing a + * connect param request from a slave if we are currently trying to + * update the connection parameters. This means that the previous + * check is all we need for a master (when receiving a request). + */ + if ((connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) || + (opcode == BLE_LL_CTRL_CONN_PARM_RSP)) { + /* + * Not sure what to do about the slave. It is possible that the + * current connection parameters are not the same ones as the local host + * has provided? Not sure what to do here. Do we need to remember what + * host sent us? For now, I will assume that we need to remember what + * the host sent us and check it out. + */ + hcu = &connsm->conn_param_req; + if (hcu->handle != 0) { + if (!((req->interval_min < hcu->conn_itvl_min) || + (req->interval_min > hcu->conn_itvl_max) || + (req->interval_max < hcu->conn_itvl_min) || + (req->interval_max > hcu->conn_itvl_max) || + (req->latency != hcu->conn_latency) || + (req->timeout != hcu->supervision_timeout))) { + indicate = 0; + } + } + } + +conn_parm_req_do_indicate: + /* + * XXX: are the connection update parameters acceptable? If not, we will + * need to know before we indicate to the host that they are acceptable. + */ + if (indicate) { + /* If Host masked out Remote Connection Parameter Request Event, we need to + * send Reject back to the remote device + */ + if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_REM_CONN_PARM_REQ)){ + ble_err = BLE_ERR_UNSUPP_REM_FEATURE; + goto conn_param_pdu_exit; + } + + /* + * Send event to host. At this point we leave and wait to get + * an answer. + */ + ble_ll_hci_ev_rem_conn_parm_req(connsm, req); + connsm->host_reply_opcode = opcode; + connsm->csmflags.cfbit.awaiting_host_reply = 1; + rsp_opcode = 255; + } else { + /* Create reply to connection request */ + rsp_opcode = ble_ll_ctrl_conn_param_reply(connsm, rspbuf, req); + } + +conn_param_pdu_exit: + if (ble_err) { + rsp_opcode = BLE_LL_CTRL_REJECT_IND_EXT; + rspbuf[1] = opcode; + rspbuf[2] = ble_err; + } + return rsp_opcode; +} + +/** + * Called to make a connection update request LL control PDU + * + * Context: Link Layer + * + * @param connsm + * @param rsp + */ +static void +ble_ll_ctrl_conn_upd_make(struct ble_ll_conn_sm *connsm, uint8_t *pyld, + struct ble_ll_conn_params *cp) +{ + uint16_t instant; + uint32_t dt; + uint32_t num_old_ce; + uint32_t new_itvl_usecs; + uint32_t old_itvl_usecs; + struct hci_conn_update *hcu; + struct ble_ll_conn_upd_req *req; + + /* + * Set instant. We set the instant to the current event counter plus + * the amount of slave latency as the slave may not be listening + * at every connection interval and we are not sure when the connect + * request will actually get sent. We add one more event plus the + * minimum as per the spec of 6 connection events. + */ + instant = connsm->event_cntr + connsm->slave_latency + 6 + 1; + + /* + * XXX: This should change in the future, but for now we will just + * start the new instant at the same anchor using win offset 0. + */ + /* Copy parameters in connection update structure */ + hcu = &connsm->conn_param_req; + req = &connsm->conn_update_req; + if (cp) { + /* XXX: so we need to make the new anchor point some time away + * from txwinoffset by some amount of msecs. Not sure how to do + that here. We dont need to, but we should. */ + /* Calculate offset from requested offsets (if any) */ + if (cp->offset0 != 0xFFFF) { + new_itvl_usecs = cp->interval_max * BLE_LL_CONN_ITVL_USECS; + old_itvl_usecs = connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS; + if ((int16_t)(cp->ref_conn_event_cnt - instant) >= 0) { + num_old_ce = cp->ref_conn_event_cnt - instant; + dt = old_itvl_usecs * num_old_ce; + dt += (cp->offset0 * BLE_LL_CONN_ITVL_USECS); + dt = dt % new_itvl_usecs; + } else { + num_old_ce = instant - cp->ref_conn_event_cnt; + dt = old_itvl_usecs * num_old_ce; + dt -= (cp->offset0 * BLE_LL_CONN_ITVL_USECS); + dt = dt % new_itvl_usecs; + dt = new_itvl_usecs - dt; + } + req->winoffset = dt / BLE_LL_CONN_TX_WIN_USECS; + } else { + req->winoffset = 0; + } + req->interval = cp->interval_max; + req->timeout = cp->timeout; + req->latency = cp->latency; + req->winsize = 1; + } else { + req->interval = hcu->conn_itvl_max; + req->timeout = hcu->supervision_timeout; + req->latency = hcu->conn_latency; + req->winoffset = 0; + req->winsize = connsm->tx_win_size; + } + req->instant = instant; + + /* XXX: make sure this works for the connection parameter request proc. */ + pyld[0] = req->winsize; + put_le16(pyld + 1, req->winoffset); + put_le16(pyld + 3, req->interval); + put_le16(pyld + 5, req->latency); + put_le16(pyld + 7, req->timeout); + put_le16(pyld + 9, instant); + + /* Set flag in state machine to denote we have scheduled an update */ + connsm->csmflags.cfbit.conn_update_sched = 1; +} + +/** + * Called to process and UNKNOWN_RSP LL control packet. + * + * Context: Link Layer Task + * + * @param dptr + */ +static int +ble_ll_ctrl_proc_unk_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr, uint8_t *rspdata) +{ + uint8_t ctrl_proc; + uint8_t opcode; + + /* Get opcode of unknown LL control frame */ + opcode = dptr[0]; + + /* Convert opcode to control procedure id */ + switch (opcode) { + case BLE_LL_CTRL_LENGTH_REQ: + ctrl_proc = BLE_LL_CTRL_PROC_DATA_LEN_UPD; + BLE_LL_CONN_CLEAR_FEATURE(connsm, BLE_LL_FEAT_DATA_LEN_EXT); + break; + case BLE_LL_CTRL_CONN_UPDATE_IND: + ctrl_proc = BLE_LL_CTRL_PROC_CONN_UPDATE; + break; + case BLE_LL_CTRL_SLAVE_FEATURE_REQ: + ctrl_proc = BLE_LL_CTRL_PROC_FEATURE_XCHG; + BLE_LL_CONN_CLEAR_FEATURE(connsm, BLE_LL_FEAT_SLAVE_INIT); + break; + case BLE_LL_CTRL_CONN_PARM_REQ: + BLE_LL_CONN_CLEAR_FEATURE(connsm, BLE_LL_FEAT_CONN_PARM_REQ); + if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + ble_ll_ctrl_conn_upd_make(connsm, rspdata, NULL); + connsm->reject_reason = BLE_ERR_SUCCESS; + return BLE_LL_CTRL_CONN_UPDATE_IND; + } + /* note: fall-through intentional */ + case BLE_LL_CTRL_CONN_PARM_RSP: + ctrl_proc = BLE_LL_CTRL_PROC_CONN_PARAM_REQ; + break; + case BLE_LL_CTRL_PING_REQ: + /* LL can authenticate remote device even if remote device does not + * support LE Ping feature. + */ + ctrl_proc = BLE_LL_CTRL_PROC_LE_PING; + BLE_LL_CONN_CLEAR_FEATURE(connsm, BLE_LL_FEAT_LE_PING); + break; +#if (BLE_LL_BT5_PHY_SUPPORTED ==1) + case BLE_LL_CTRL_PHY_REQ: + ble_ll_ctrl_phy_update_cancel(connsm, BLE_ERR_UNSUPP_REM_FEATURE); + ctrl_proc = BLE_LL_CTRL_PROC_PHY_UPDATE; + break; +#endif + default: + ctrl_proc = BLE_LL_CTRL_PROC_NUM; + break; + } + + /* If we are running this one currently, stop it */ + if (connsm->cur_ctrl_proc == ctrl_proc) { + /* Stop the control procedure */ + ble_ll_ctrl_proc_stop(connsm, ctrl_proc); + if (ctrl_proc == BLE_LL_CTRL_PROC_CONN_PARAM_REQ) { + ble_ll_hci_ev_conn_update(connsm, BLE_ERR_UNSUPP_REM_FEATURE); + } else if (ctrl_proc == BLE_LL_CTRL_PROC_FEATURE_XCHG) { + if (connsm->csmflags.cfbit.pending_hci_rd_features) { + ble_ll_hci_ev_rd_rem_used_feat(connsm, + BLE_ERR_UNSUPP_REM_FEATURE); + } + connsm->csmflags.cfbit.pending_hci_rd_features = 0; + } + } + + return BLE_ERR_MAX; +} + +/** + * Callback when LL control procedure times out (for a given connection). If + * this is called, it means that we need to end the connection because it + * has not responded to a LL control request. + * + * Context: Link Layer + * + * @param arg Pointer to connection state machine. + */ +static void +ble_ll_ctrl_proc_rsp_timer_cb(struct ble_npl_event *ev) +{ + /* Control procedure has timed out. Kill the connection */ + ble_ll_conn_timeout((struct ble_ll_conn_sm *)ble_npl_event_get_arg(ev), + BLE_ERR_LMP_LL_RSP_TMO); +} + +static void +ble_ll_ctrl_start_rsp_timer(struct ble_ll_conn_sm *connsm) +{ + ble_npl_callout_init(&connsm->ctrl_proc_rsp_timer, + &g_ble_ll_data.ll_evq, + ble_ll_ctrl_proc_rsp_timer_cb, + connsm); + + /* Re-start timer. Control procedure timeout is 40 seconds */ + ble_npl_callout_reset(&connsm->ctrl_proc_rsp_timer, + ble_npl_time_ms_to_ticks32(BLE_LL_CTRL_PROC_TIMEOUT_MS)); +} + +/** + * Convert a phy mask to a numeric phy value. + * + * NOTE: only one bit should be set here and there should be at least one. + * If this function returns a 0 it is an error! + * + * @param phy_mask Bitmask of phy + * + * @return uint8_t The numeric value associated with the phy mask + * + * BLE_HCI_LE_PHY_1M (1) + * BLE_HCI_LE_PHY_2M (2) + * BLE_HCI_LE_PHY_CODED (3) + */ +uint8_t +ble_ll_ctrl_phy_from_phy_mask(uint8_t phy_mask) +{ + uint8_t phy; + + /* + * NOTE: wipe out unsupported PHYs. There should not be an unsupported + * in this mask if the other side is working correctly. + */ +#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) + phy_mask &= ~BLE_HCI_LE_PHY_2M_PREF_MASK; +#endif +#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + phy_mask &= ~BLE_HCI_LE_PHY_CODED_PREF_MASK; +#endif + + if (phy_mask & BLE_PHY_MASK_1M) { + phy = BLE_PHY_1M; + phy_mask &= ~BLE_PHY_MASK_1M; + } else if (phy_mask & BLE_PHY_MASK_2M) { + phy = BLE_PHY_2M; + phy_mask &= ~BLE_PHY_MASK_2M; + } else if (phy_mask & BLE_PHY_MASK_CODED) { + phy = BLE_PHY_CODED; + phy_mask &= ~BLE_PHY_MASK_CODED; + } else { + phy = 0; + } + + if (phy_mask != 0) { + phy = 0; + } + + return phy; +} + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +uint8_t +ble_ll_ctrl_phy_tx_transition_get(uint8_t phy_mask) +{ + /* + * Evaluate PHYs in transition starting from the one with longest TX time + * so we select the one that allows shortest payload to be sent. This is + * to make sure we do not violate timing restriction on new PHY. + */ + if (phy_mask & BLE_PHY_MASK_CODED) { + return BLE_PHY_CODED; + } else if (phy_mask & BLE_PHY_MASK_1M) { + return BLE_PHY_1M; + } else if (phy_mask & BLE_PHY_MASK_2M) { + return BLE_PHY_2M; + } + + return 0; +} + +void +ble_ll_ctrl_phy_update_proc_complete(struct ble_ll_conn_sm *connsm) +{ + int chk_proc_stop; + int chk_host_phy; + + chk_proc_stop = 1; + chk_host_phy = 1; + + connsm->phy_tx_transition = 0; + + if (CONN_F_PEER_PHY_UPDATE(connsm)) { + CONN_F_PEER_PHY_UPDATE(connsm) = 0; + } else if (CONN_F_CTRLR_PHY_UPDATE(connsm)) { + CONN_F_CTRLR_PHY_UPDATE(connsm) = 0; + } else { + /* Must be a host-initiated update */ + CONN_F_HOST_PHY_UPDATE(connsm) = 0; + chk_host_phy = 0; + if (CONN_F_PHY_UPDATE_EVENT(connsm) == 0) { + ble_ll_hci_ev_phy_update(connsm, BLE_ERR_SUCCESS); + } + } + + /* Must check if we need to start host procedure */ + if (chk_host_phy) { + if (CONN_F_HOST_PHY_UPDATE(connsm)) { + if (ble_ll_conn_chk_phy_upd_start(connsm)) { + CONN_F_HOST_PHY_UPDATE(connsm) = 0; + } else { + chk_proc_stop = 0; + } + } + } + + if (chk_proc_stop) { + ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE); + } +} + +/** + * + * There is probably a better way for the controller to choose which PHY use. + * There are no BER metrics and RSSI does not give you S/N so for now we will + * choose this heirarchy: + * -> if 2Mbps available, use it. + * -> If 1Mbps available, use it. + * -> otherwise use coded phy. + * + * @param prefs The mask of preferred phys + * @return uint8_t The phy to use (not a mask) + */ +static uint8_t +ble_ll_ctrl_find_new_phy(uint8_t phy_mask_prefs) +{ + uint8_t new_phy; + + new_phy = phy_mask_prefs; + if (new_phy) { + if (new_phy & BLE_PHY_MASK_2M) { + new_phy = BLE_PHY_2M; + } else if (new_phy & BLE_PHY_MASK_1M) { + new_phy = BLE_PHY_1M; + } else { + new_phy = BLE_PHY_CODED; + } + } + + return new_phy; +} + +/** + * Create a LL_PHY_UPDATE_IND pdu + * + * @param connsm Pointer to connection state machine + * @param dptr Pointer to PHY_REQ or PHY_RSP data. + * @param ctrdata: Pointer to where CtrData of UPDATE_IND pdu starts + * @param slave_req flag denoting if slave requested this. 0: no 1:yes + */ +static void +ble_ll_ctrl_phy_update_ind_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr, + uint8_t *ctrdata, int slave_req) +{ + uint8_t m_to_s; + uint8_t s_to_m; + uint8_t tx_phys; + uint8_t rx_phys; + uint16_t instant; + uint8_t is_slave_sym = 0; + + /* Get preferences from PDU */ + tx_phys = dptr[0]; + rx_phys = dptr[1]; + + /* If we are master, check if slave requested symmetric PHY */ + if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + is_slave_sym = tx_phys == rx_phys; + is_slave_sym &= __builtin_popcount(tx_phys) == 1; + } + + /* Get m_to_s and s_to_m masks */ + if (slave_req) { + m_to_s = connsm->phy_data.host_pref_tx_phys_mask & rx_phys; + s_to_m = connsm->phy_data.host_pref_rx_phys_mask & tx_phys; + } else { + m_to_s = connsm->phy_data.req_pref_tx_phys_mask & rx_phys; + s_to_m = connsm->phy_data.req_pref_rx_phys_mask & tx_phys; + } + + if (is_slave_sym) { + /* + * If either s_to_m or m_to_s is 0, it means for at least one direction + * requested PHY is not our preferred one so make sure we keep current + * PHY in both directions + * + * Core 5.2, Vol 6, PartB, 5.1.10 + * If the slave specified a single PHY in both the TX_PHYS and + * RX_PHYS fields and both fields are the same, the master shall + * either select the PHY specified by the slave for both directions + * or shall leave both directions unchanged. + */ + if ((s_to_m == 0) || (m_to_s == 0)) { + s_to_m = 0; + m_to_s = 0; + } else { + BLE_LL_ASSERT(s_to_m == m_to_s); + } + } + + /* Calculate new PHYs to use */ + m_to_s = ble_ll_ctrl_find_new_phy(m_to_s); + s_to_m = ble_ll_ctrl_find_new_phy(s_to_m); + + /* Make sure we do not indicate PHY change if the same as current one */ + if (m_to_s == connsm->phy_data.cur_tx_phy) { + m_to_s = 0; + } + if (s_to_m == connsm->phy_data.cur_rx_phy) { + s_to_m = 0; + } + + /* At this point, m_to_s and s_to_m are not masks; they are numeric */ + + /* + * If not changing we still send update ind. Check if hosts expects + * the event and if so send it. Stop control procedure if it is the + * one running. + */ + if ((m_to_s == 0) && (s_to_m == 0)) { + if (CONN_F_PEER_PHY_UPDATE(connsm)) { + CONN_F_PEER_PHY_UPDATE(connsm) = 0; + } else if (CONN_F_CTRLR_PHY_UPDATE(connsm)) { + CONN_F_CTRLR_PHY_UPDATE(connsm) = 0; + ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE); + } else { + ble_ll_hci_ev_phy_update(connsm, BLE_ERR_SUCCESS); + CONN_F_HOST_PHY_UPDATE(connsm) = 0; + ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE); + } + instant = 0; + } else { + /* Determine instant we will use. 6 more is minimum */ + instant = connsm->event_cntr + connsm->slave_latency + 6 + 1; + connsm->phy_instant = instant; + CONN_F_PHY_UPDATE_SCHED(connsm) = 1; + + /* Set new phys to use when instant occurs */ + connsm->phy_data.new_tx_phy = m_to_s; + connsm->phy_data.new_rx_phy = s_to_m; + + /* Convert m_to_s and s_to_m to masks */ + if (m_to_s) { + m_to_s = 1 << (m_to_s - 1); + } + + if (s_to_m) { + s_to_m = 1 << (s_to_m - 1); + } + } + + ctrdata[0] = m_to_s; + ctrdata[1] = s_to_m; + put_le16(ctrdata + 2, instant); +} + +/** + * Create a LL_PHY_REQ or LL_PHY_RSP pdu + * + * @param connsm Pointer to connection state machine + * @param ctrdata: Pointer to where CtrData starts in pdu + */ +static void +ble_ll_ctrl_phy_req_rsp_make(struct ble_ll_conn_sm *connsm, uint8_t *ctrdata) +{ + /* If no preference we use current phy */ + if (connsm->phy_data.host_pref_tx_phys_mask == 0) { + ctrdata[0] = CONN_CUR_TX_PHY_MASK(connsm); + } else { + ctrdata[0] = connsm->phy_data.host_pref_tx_phys_mask; + } + if (connsm->phy_data.host_pref_rx_phys_mask == 0) { + ctrdata[1] = CONN_CUR_RX_PHY_MASK(connsm); + } else { + ctrdata[1] = connsm->phy_data.host_pref_rx_phys_mask; + } +} + +static uint8_t +ble_ll_ctrl_rx_phy_req(struct ble_ll_conn_sm *connsm, uint8_t *req, + uint8_t *rsp) +{ + uint8_t rsp_opcode; + uint8_t err; + + /* + * XXX: TODO if we have an instant in progress we should end connection. + * At least it seems that is the case. Need to figure out more from + * the spec here. + */ + + /* Check if we have already initiated a procedure with an instant */ + err = ble_ll_ctrl_proc_with_instant_initiated(connsm, + BLE_LL_CTRL_PROC_PHY_UPDATE); + + if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + if (err) { + ble_ll_ctrl_rej_ext_ind_make(BLE_LL_CTRL_PHY_REQ, err, rsp); + rsp_opcode = BLE_LL_CTRL_REJECT_IND_EXT; + } else { + /* + * NOTE: do not change order of these two lines as the call to + * make the LL_PHY_UPDATE_IND pdu might clear the flag. + */ + CONN_F_PEER_PHY_UPDATE(connsm) = 1; + ble_ll_ctrl_phy_update_ind_make(connsm, req, rsp, 1); + rsp_opcode = BLE_LL_CTRL_PHY_UPDATE_IND; + } + } else { + /* XXX: deal with other control procedures that we need to stop */ + if (err) { + if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_PHY_UPDATE) { + ble_npl_callout_stop(&connsm->ctrl_proc_rsp_timer); + connsm->cur_ctrl_proc = BLE_LL_CTRL_PROC_IDLE; + } + + /* If there is a PHY update procedure pending cancel it */ + ble_ll_ctrl_phy_update_cancel(connsm, err); + + /* XXX: ? Should not be any phy update events */ + CONN_F_PHY_UPDATE_EVENT(connsm) = 0; + } + + /* XXX: TODO: if we started another procedure with an instant + * why are we doing this? Need to look into this.*/ + + /* Respond to master's phy update procedure */ + CONN_F_PEER_PHY_UPDATE(connsm) = 1; + ble_ll_ctrl_phy_req_rsp_make(connsm, rsp); + rsp_opcode = BLE_LL_CTRL_PHY_RSP; + + connsm->phy_tx_transition = ble_ll_ctrl_phy_tx_transition_get(req[1] | rsp[0]); + + /* Start response timer */ + connsm->cur_ctrl_proc = BLE_LL_CTRL_PROC_PHY_UPDATE; + ble_ll_ctrl_start_rsp_timer(connsm); + } + return rsp_opcode; +} + +/** + * Process a received LL_PHY_RSP pdu + * + * @param connsm + * @param dptr Pointer to LL_PHY_RSP ctrdata + * @param rsp Pointer to CtrData of PHY_UPDATE_IND. + * + * @return uint8_t + */ +static uint8_t +ble_ll_ctrl_rx_phy_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr, + uint8_t *rsp) +{ + uint8_t rsp_opcode; + + rsp_opcode = BLE_ERR_MAX; + if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_PHY_UPDATE) { + ble_ll_ctrl_phy_update_ind_make(connsm, dptr, rsp, 0); + ble_npl_callout_stop(&connsm->ctrl_proc_rsp_timer); + rsp_opcode = BLE_LL_CTRL_PHY_UPDATE_IND; + } + + /* + * If not in the process of doing this control procedure something + * is wrong. End connection? Assert? + * + * XXX: TODO count some stat? + */ + } else { + rsp_opcode = BLE_LL_CTRL_UNKNOWN_RSP; + } + + /* NOTE: slave should never receive one of these */ + + return rsp_opcode; +} + +/** + * Called when a LL_PHY_UPDATE_IND pdu is received + * + * NOTE: slave is the only device that should receive this. + * + * @param connsm + * @param dptr + * + * @return uint8_t + */ +static uint8_t +ble_ll_ctrl_rx_phy_update_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr) +{ + int no_change; + uint8_t new_m_to_s_mask; + uint8_t new_s_to_m_mask; + uint8_t new_tx_phy; + uint8_t new_rx_phy; + uint16_t instant; + uint16_t delta; + + if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + return BLE_LL_CTRL_UNKNOWN_RSP; + } + + /* + * Reception stops the procedure response timer but does not + * complete the procedure + */ + if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_PHY_UPDATE) { + ble_npl_callout_stop(&connsm->ctrl_proc_rsp_timer); + } + + /* + * XXX: Should we check to see if we are expecting to receive one + * of these, and if not, kill connection? Meaning we better be + * doing either a PEER, CTRLR, or HOST phy update. + */ + /* get the new phy masks and see if we need to change */ + new_m_to_s_mask = dptr[0]; + new_s_to_m_mask = dptr[1]; + instant = get_le16(dptr + 2); + + if ((new_m_to_s_mask == 0) && (new_s_to_m_mask == 0)) { + /* No change in phy */ + no_change = 1; + } else { + no_change = 0; + /* + * NOTE: from the slaves perspective, the m to s phy is the one + * that the slave will receive on; s to m is the one it will + * transmit on + */ + new_rx_phy = ble_ll_ctrl_phy_from_phy_mask(new_m_to_s_mask); + new_tx_phy = ble_ll_ctrl_phy_from_phy_mask(new_s_to_m_mask); + + if ((new_tx_phy == 0) && (new_rx_phy == 0)) { + /* XXX: this is an error! What to do??? */ + no_change = 1; + } + + if ((new_tx_phy == connsm->phy_data.cur_tx_phy) && + (new_rx_phy == connsm->phy_data.cur_rx_phy)) { + no_change = 1; + } + } + + if (!no_change) { + /* If instant is in the past, we have to end the connection */ + delta = (instant - connsm->event_cntr) & 0xFFFF; + if (delta >= 32767) { + ble_ll_conn_timeout(connsm, BLE_ERR_INSTANT_PASSED); + } else { + connsm->phy_data.new_tx_phy = new_tx_phy; + connsm->phy_data.new_rx_phy = new_rx_phy; + connsm->phy_instant = instant; + CONN_F_PHY_UPDATE_SCHED(connsm) = 1; + } + return BLE_ERR_MAX; + } + + ble_ll_ctrl_phy_update_proc_complete(connsm); + + return BLE_ERR_MAX; +} +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) +/** + * Called when a BLE_LL_CTRL_PERIODIC_SYNC_IND PDU is received + * + * @param connsm + * @param dptr + * + * @return uint8_t + */ +static uint8_t +ble_ll_ctrl_rx_periodic_sync_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr) +{ + if (connsm->sync_transfer_mode) { + ble_ll_sync_periodic_ind(connsm, dptr, connsm->sync_transfer_mode == 1, + connsm->sync_transfer_skip, + connsm->sync_transfer_sync_timeout); + } + + return BLE_ERR_MAX; +} +#endif + +/** + * Create a link layer length request or length response PDU. + * + * NOTE: this function does not set the LL data pdu header nor does it + * set the opcode in the buffer. + * + * @param connsm + * @param dptr: Pointer to where control pdu payload starts + */ +static void +ble_ll_ctrl_datalen_upd_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr) +{ + put_le16(dptr + 1, connsm->max_rx_octets); + put_le16(dptr + 3, connsm->max_rx_time); + put_le16(dptr + 5, connsm->max_tx_octets); + put_le16(dptr + 7, connsm->max_tx_time); +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) +void +ble_ll_calc_session_key(struct ble_ll_conn_sm *connsm) +{ +#ifdef BLE_LL_ENCRYPT_DEBUG + int cnt; +#endif + + /* XXX: possibly have some way out of this if this locks up */ + while (1) { + if (!ble_hw_encrypt_block(&connsm->enc_data.enc_block)) { + break; + } + } + +#ifdef BLE_LL_ENCRYPT_DEBUG + console_printf("Calculating Session Key for handle=%u", + connsm->conn_handle); + + console_printf("\nLTK:"); + for (cnt = 0; cnt < 16; ++cnt) { + console_printf("%02x", connsm->enc_data.enc_block.key[cnt]); + } + console_printf("\nSKD:"); + for (cnt = 0; cnt < 16; ++cnt) { + console_printf("%02x", connsm->enc_data.enc_block.plain_text[cnt]); + } + console_printf("\nSession Key:"); + for (cnt = 0; cnt < 16; ++cnt) { + console_printf("%02x", connsm->enc_data.enc_block.cipher_text[cnt]); + } + console_printf("\nIV:"); + for (cnt = 0; cnt < 8; ++ cnt) { + console_printf("%02x", connsm->enc_data.iv[cnt]); + } + console_printf("\n"); +#endif +} + +/** + * Called to determine if this is a control PDU we are allowed to send. This + * is called when a link is being encrypted, as only certain control PDU's + * area lowed to be sent. + * + * XXX: the current code may actually allow some control pdu's to be sent + * in states where they shouldnt. I dont expect those states to occur so I + * dont try to check for them but we could do more... for example there are + * different PDUs allowed for master/slave and TX/RX + * + * @param llid + * @param opcode + * @param len + * + * @return int + */ +static int +ble_ll_ctrl_enc_allowed_pdu(uint8_t llid, uint8_t len, uint8_t opcode) +{ + int allowed; + + allowed = 0; + + switch (llid) { + case BLE_LL_LLID_CTRL: + switch (opcode) { + case BLE_LL_CTRL_REJECT_IND: + case BLE_LL_CTRL_REJECT_IND_EXT: + case BLE_LL_CTRL_START_ENC_RSP: + case BLE_LL_CTRL_START_ENC_REQ: + case BLE_LL_CTRL_ENC_REQ: + case BLE_LL_CTRL_ENC_RSP: + case BLE_LL_CTRL_PAUSE_ENC_REQ: + case BLE_LL_CTRL_PAUSE_ENC_RSP: + case BLE_LL_CTRL_TERMINATE_IND: + allowed = 1; + break; + } + break; + case BLE_LL_LLID_DATA_FRAG: + if (len == 0) { + /* Empty PDUs are allowed */ + allowed = 1; + } + break; + } + + return allowed; +} + +int +ble_ll_ctrl_enc_allowed_pdu_rx(struct os_mbuf *rxpdu) +{ + uint8_t llid; + uint8_t len; + uint8_t opcode; + + llid = rxpdu->om_data[0] & BLE_LL_DATA_HDR_LLID_MASK; + len = rxpdu->om_data[1]; + if (llid == BLE_LL_LLID_CTRL) { + opcode = rxpdu->om_data[2]; + } else { + opcode = 0; + } + + return ble_ll_ctrl_enc_allowed_pdu(llid, len, opcode); +} + +int +ble_ll_ctrl_enc_allowed_pdu_tx(struct os_mbuf_pkthdr *pkthdr) +{ + struct os_mbuf *m; + struct ble_mbuf_hdr *ble_hdr; + uint8_t llid; + uint8_t len; + uint8_t opcode; + + m = OS_MBUF_PKTHDR_TO_MBUF(pkthdr); + ble_hdr = BLE_MBUF_HDR_PTR(m); + + llid = ble_hdr->txinfo.hdr_byte & BLE_LL_DATA_HDR_LLID_MASK; + len = ble_hdr->txinfo.pyld_len; + if (llid == BLE_LL_LLID_CTRL) { + opcode = m->om_data[0]; + } else { + opcode = 0; + } + + return ble_ll_ctrl_enc_allowed_pdu(llid, len, opcode); +} + +int +ble_ll_ctrl_is_start_enc_rsp(struct os_mbuf *txpdu) +{ + int is_start_enc_rsp; + uint8_t opcode; + uint8_t llid; + struct ble_mbuf_hdr *ble_hdr; + + is_start_enc_rsp = 0; + ble_hdr = BLE_MBUF_HDR_PTR(txpdu); + + llid = ble_hdr->txinfo.hdr_byte & BLE_LL_DATA_HDR_LLID_MASK; + if (llid == BLE_LL_LLID_CTRL) { + opcode = txpdu->om_data[0]; + if (opcode == BLE_LL_CTRL_START_ENC_RSP) { + is_start_enc_rsp = 1; + } + } + + return is_start_enc_rsp; +} + +/** + * Called to create and send a LL_START_ENC_REQ + * + * @param connsm + * @param err + * + * @return int + */ +int +ble_ll_ctrl_start_enc_send(struct ble_ll_conn_sm *connsm) +{ + int rc; + struct os_mbuf *om; + + om = os_msys_get_pkthdr(BLE_LL_CTRL_MAX_PDU_LEN, + sizeof(struct ble_mbuf_hdr)); + if (om) { + om->om_data[0] = BLE_LL_CTRL_START_ENC_REQ; + ble_ll_conn_enqueue_pkt(connsm, om, BLE_LL_LLID_CTRL, 1); + + /* Wait for LL_START_ENC_RSP. If there is already procedure in progress, + * LL response timer is already running. + */ + if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_IDLE) { + connsm->cur_ctrl_proc = BLE_LL_CTRL_PROC_ENCRYPT; + ble_ll_ctrl_start_rsp_timer(connsm); + } + + rc = 0; + } else { + rc = -1; + } + return rc; +} + +/** + * Create a link layer control "encrypt request" PDU. + * + * The LL_ENC_REQ PDU format is: + * Rand (8) + * EDIV (2) + * SKDm (8) + * IVm (4) + * + * The random number and encrypted diversifier come from the host command. + * Controller generates master portion of SDK and IV. + * + * NOTE: this function does not set the LL data pdu header nor does it + * set the opcode in the buffer. + * + * @param connsm + * @param dptr: Pointer to where control pdu payload starts + */ +static void +ble_ll_ctrl_enc_req_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr) +{ + put_le64(dptr, connsm->enc_data.host_rand_num); + put_le16(dptr + 8, connsm->enc_data.enc_div); + +#ifdef BLE_LL_ENCRYPT_USE_TEST_DATA + /* IV stored LSB to MSB, IVm is LSB, IVs is MSB */ + put_le64(dptr + 10, g_bletest_SKDm); + swap_buf(connsm->enc_data.enc_block.plain_text + 8, dptr + 10, 8); + put_le32(dptr + 18, g_bletest_IVm); + memcpy(connsm->enc_data.iv, dptr + 18, 4); + return; +#endif + + ble_ll_rand_data_get(connsm->enc_data.enc_block.plain_text + 8, 8); + swap_buf(dptr + 10, connsm->enc_data.enc_block.plain_text + 8, 8); + ble_ll_rand_data_get(connsm->enc_data.iv, 4); + memcpy(dptr + 18, connsm->enc_data.iv, 4); +} + +/** + * Called when LL_ENC_RSP is received by the master. + * + * Context: Link Layer Task. + * + * Format of the LL_ENC_RSP is: + * SKDs (8) + * IVs (4) + * + * The master now has the long term key (from the start encrypt command) + * and the SKD (stored in the plain text encryption block). From this the + * sessionKey is generated. + * + * @param connsm + * @param dptr + */ +static void +ble_ll_ctrl_rx_enc_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr) +{ + /* Calculate session key now that we have received the ENC_RSP */ + if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_ENCRYPT) { + /* In case we were already encrypted we need to reset packet counters */ + connsm->enc_data.rx_pkt_cntr = 0; + connsm->enc_data.tx_pkt_cntr = 0; + connsm->enc_data.tx_encrypted = 0; + + swap_buf(connsm->enc_data.enc_block.plain_text, dptr, 8); + memcpy(connsm->enc_data.iv + 4, dptr + 8, 4); + ble_ll_calc_session_key(connsm); + connsm->enc_data.enc_state = CONN_ENC_S_START_ENC_REQ_WAIT; + } +} + +/** + * Called when we have received a LL control encryption request PDU. This + * should only be received by a slave. + * + * The LL_ENC_REQ PDU format is: + * Rand (8) + * EDIV (2) + * SKDm (8) + * IVm (4) + * + * This function returns the response opcode. Typically this will be ENC_RSP + * but it could be a reject ind. Note that the caller of this function + * will send the REJECT_IND_EXT if supported by remote. + * + * NOTE: if this is received by a master we will silently discard the PDU + * (denoted by return BLE_ERR_MAX). + * + * @param connsm + * @param dptr Pointer to start of encrypt request data. + * @param rspbuf + */ +static uint8_t +ble_ll_ctrl_rx_enc_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr, + uint8_t *rspdata) +{ + if (connsm->conn_role != BLE_LL_CONN_ROLE_SLAVE) { + return BLE_LL_CTRL_UNKNOWN_RSP; + } + + connsm->enc_data.enc_state = CONN_ENC_S_LTK_REQ_WAIT; + + /* In case we were already encrypted we need to reset packet counters */ + connsm->enc_data.rx_pkt_cntr = 0; + connsm->enc_data.tx_pkt_cntr = 0; + connsm->enc_data.tx_encrypted = 0; + + /* Extract information from request */ + connsm->enc_data.host_rand_num = get_le64(dptr); + connsm->enc_data.enc_div = get_le16(dptr + 8); + +#if BLE_LL_ENCRYPT_USE_TEST_DATA + swap_buf(connsm->enc_data.enc_block.plain_text + 8, dptr + 10, 8); + memcpy(connsm->enc_data.iv, dptr + 18, 4); + + put_le64(rspdata, g_bletest_SKDs); + swap_buf(connsm->enc_data.enc_block.plain_text, rspdata, 8); + put_le32(rspdata + 8, g_bletest_IVs); + memcpy(connsm->enc_data.iv + 4, rspdata + 8, 4); + return BLE_LL_CTRL_ENC_RSP; +#endif + + swap_buf(connsm->enc_data.enc_block.plain_text + 8, dptr + 10, 8); + memcpy(connsm->enc_data.iv, dptr + 18, 4); + + /* Create the ENC_RSP. Concatenate our SKD and IV */ + ble_ll_rand_data_get(connsm->enc_data.enc_block.plain_text, 8); + swap_buf(rspdata, connsm->enc_data.enc_block.plain_text, 8); + ble_ll_rand_data_get(connsm->enc_data.iv + 4, 4); + memcpy(rspdata + 8, connsm->enc_data.iv + 4, 4); + + return BLE_LL_CTRL_ENC_RSP; +} + +static uint8_t +ble_ll_ctrl_rx_start_enc_req(struct ble_ll_conn_sm *connsm) +{ + int rc; + + /* Only master should receive start enc request */ + rc = BLE_ERR_MAX; + if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + /* We only want to send a START_ENC_RSP if we havent yet */ + if (connsm->enc_data.enc_state == CONN_ENC_S_START_ENC_REQ_WAIT) { + connsm->enc_data.enc_state = CONN_ENC_S_START_ENC_RSP_WAIT; + rc = BLE_LL_CTRL_START_ENC_RSP; + } + } else { + rc = BLE_LL_CTRL_UNKNOWN_RSP; + } + return rc; +} + +static uint8_t +ble_ll_ctrl_rx_pause_enc_req(struct ble_ll_conn_sm *connsm) +{ + int rc; + + /* + * The spec does not say what to do here, but if we receive a pause + * encryption request and we are not encrypted, what do we do? We + * ignore it... + */ + rc = BLE_ERR_MAX; + if ((connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) && + (connsm->enc_data.enc_state == CONN_ENC_S_ENCRYPTED)) { + rc = BLE_LL_CTRL_PAUSE_ENC_RSP; + } else { + rc = BLE_LL_CTRL_UNKNOWN_RSP; + } + + return rc; +} + +/** + * Called when a LL control pdu with opcode PAUSE_ENC_RSP is received. + * + * + * @param connsm + * + * @return uint8_t + */ +static uint8_t +ble_ll_ctrl_rx_pause_enc_rsp(struct ble_ll_conn_sm *connsm) +{ + int rc; + + if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + rc = BLE_LL_CTRL_PAUSE_ENC_RSP; + } else if (connsm->enc_data.enc_state == CONN_ENC_S_PAUSE_ENC_RSP_WAIT) { + /* Master sends back unencrypted LL_PAUSE_ENC_RSP. + * From this moment encryption is paused. + */ + rc = BLE_ERR_MAX; + connsm->enc_data.enc_state = CONN_ENC_S_PAUSED; + } else { + rc = BLE_LL_CTRL_UNKNOWN_RSP; + } + + return rc; +} + +/** + * Called when we have received a LL_CTRL_START_ENC_RSP. + * + * Context: Link-layer task + * + * @param connsm + * + * @return uint8_t + */ +static uint8_t +ble_ll_ctrl_rx_start_enc_rsp(struct ble_ll_conn_sm *connsm) +{ + int rc; + + /* Not in proper state. Discard */ + if (connsm->enc_data.enc_state != CONN_ENC_S_START_ENC_RSP_WAIT) { + return BLE_ERR_MAX; + } + + /* If master, we are done. Stop control procedure and sent event to host */ + if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + + ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_ENCRYPT); + + /* We are encrypted */ + connsm->enc_data.enc_state = CONN_ENC_S_ENCRYPTED; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) + ble_ll_conn_auth_pyld_timer_start(connsm); +#endif + rc = BLE_ERR_MAX; + } else { + /* Procedure has completed but slave needs to send START_ENC_RSP */ + rc = BLE_LL_CTRL_START_ENC_RSP; + + /* Stop timer if it was started when sending START_ENC_REQ */ + if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_ENCRYPT) { + ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_ENCRYPT); + } + } + + /* + * XXX: for now, a Slave sends this event when it receivest the + * START_ENC_RSP from the master. It might be technically incorrect + * to send it before we transmit our own START_ENC_RSP. + */ + ble_ll_hci_ev_encrypt_chg(connsm, BLE_ERR_SUCCESS); + + return rc; +} + +#endif + +/** + * Called to make a connection parameter request or response control pdu. + * + * @param connsm + * @param dptr Pointer to start of data. NOTE: the opcode is not part + * of the data. + */ +static void +ble_ll_ctrl_conn_param_pdu_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr, + struct ble_ll_conn_params *req) +{ + uint16_t offset; + struct hci_conn_update *hcu; + + /* If we were passed in a request, we use the parameters from the request */ + if (req) { + put_le16(dptr, req->interval_min); + put_le16(dptr + 2, req->interval_max); + put_le16(dptr + 4, req->latency); + put_le16(dptr + 6, req->timeout); + } else { + hcu = &connsm->conn_param_req; + /* The host should have provided the parameters! */ + BLE_LL_ASSERT(hcu->handle != 0); + put_le16(dptr, hcu->conn_itvl_min); + put_le16(dptr + 2, hcu->conn_itvl_max); + put_le16(dptr + 4, hcu->conn_latency); + put_le16(dptr + 6, hcu->supervision_timeout); + } + + /* XXX: NOTE: if interval min and interval max are != to each + * other this value should be set to non-zero. I think this + * applies only when an offset field is set. See section 5.1.7.1 pg 103 + * Vol 6 Part B. + */ + /* XXX: for now, set periodicity to 0 */ + dptr[8] = 0; + + /* XXX: deal with reference event count. what to put here? */ + put_le16(dptr + 9, connsm->event_cntr); + + /* XXX: For now, dont use offsets */ + offset = 0xFFFF; + put_le16(dptr + 11, offset); + put_le16(dptr + 13, offset); + put_le16(dptr + 15, offset); + put_le16(dptr + 17, offset); + put_le16(dptr + 19, offset); + put_le16(dptr + 21, offset); +} + +static void +ble_ll_ctrl_version_ind_make(struct ble_ll_conn_sm *connsm, uint8_t *pyld) +{ + /* Set flag to denote we have sent/received this */ + connsm->csmflags.cfbit.version_ind_sent = 1; + + /* Fill out response */ + pyld[0] = BLE_HCI_VER_BCS; + put_le16(pyld + 1, MYNEWT_VAL(BLE_LL_MFRG_ID)); + put_le16(pyld + 3, BLE_LL_SUB_VERS_NR); +} + +/** + * Called to make a LL control channel map request PDU. + * + * @param connsm Pointer to connection state machine + * @param pyld Pointer to payload of LL control PDU + */ +static void +ble_ll_ctrl_chanmap_req_make(struct ble_ll_conn_sm *connsm, uint8_t *pyld) +{ + /* Copy channel map that host desires into request */ + memcpy(pyld, g_ble_ll_conn_params.master_chan_map, BLE_LL_CONN_CHMAP_LEN); + memcpy(connsm->req_chanmap, pyld, BLE_LL_CONN_CHMAP_LEN); + + /* Place instant into request */ + connsm->chanmap_instant = connsm->event_cntr + connsm->slave_latency + 6 + 1; + put_le16(pyld + BLE_LL_CONN_CHMAP_LEN, connsm->chanmap_instant); + + /* Set scheduled flag */ + connsm->csmflags.cfbit.chanmap_update_scheduled = 1; +} + +/** + * Called to respond to a LL control PDU connection parameter request or + * response. + * + * @param connsm + * @param rsp + * @param req + * + * @return uint8_t + */ +uint8_t +ble_ll_ctrl_conn_param_reply(struct ble_ll_conn_sm *connsm, uint8_t *rsp, + struct ble_ll_conn_params *req) +{ + uint8_t rsp_opcode; + + if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { + /* Create a connection parameter response */ + ble_ll_ctrl_conn_param_pdu_make(connsm, rsp + 1, req); + rsp_opcode = BLE_LL_CTRL_CONN_PARM_RSP; + } else { + /* Create a connection update pdu */ + ble_ll_ctrl_conn_upd_make(connsm, rsp + 1, req); + rsp_opcode = BLE_LL_CTRL_CONN_UPDATE_IND; + } + + return rsp_opcode; +} + +/** + * Called when we have received a LL_REJECT_IND or LL_REJECT_IND_EXT link + * layer control Data Channel pdu. + * + * @param connsm + * @param dptr + * @param opcode + */ +static int +ble_ll_ctrl_rx_reject_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr, + uint8_t opcode, uint8_t *rspdata) +{ + uint8_t ble_error; + uint8_t rsp_opcode = BLE_ERR_MAX; + + /* Get error out of received PDU */ + if (opcode == BLE_LL_CTRL_REJECT_IND) { + ble_error = dptr[0]; + } else { + ble_error = dptr[1]; + } + + /* XXX: should I check to make sure the rejected opcode is sane + if we receive ind ext? */ + switch (connsm->cur_ctrl_proc) { + case BLE_LL_CTRL_PROC_CONN_PARAM_REQ: + if (opcode == BLE_LL_CTRL_REJECT_IND_EXT) { + /* As a master we should send connection update indication in this point */ + if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + rsp_opcode = BLE_LL_CTRL_CONN_UPDATE_IND; + ble_ll_ctrl_conn_upd_make(connsm, rspdata, NULL); + connsm->reject_reason = BLE_ERR_SUCCESS; + } else { + ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ); + ble_ll_hci_ev_conn_update(connsm, ble_error); + } + } + break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + case BLE_LL_CTRL_PROC_ENCRYPT: + ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_ENCRYPT); + ble_ll_hci_ev_encrypt_chg(connsm, ble_error); + connsm->enc_data.enc_state = CONN_ENC_S_UNENCRYPTED; + break; +#endif +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + case BLE_LL_CTRL_PROC_PHY_UPDATE: + ble_ll_ctrl_phy_update_cancel(connsm, ble_error); + ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE); + break; +#endif + case BLE_LL_CTRL_PROC_DATA_LEN_UPD: + /* That should not happen according to Bluetooth 5.0 Vol6 Part B, 5.1.9 + * However we need this workaround as there are devices on the market + * which do send LL_REJECT on LL_LENGTH_REQ when collision happens + */ + ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD); + break; + default: + break; + } + + return rsp_opcode; +} + +/** + * Called when we receive a connection update event + * + * @param connsm + * @param dptr + * + * @return int + */ +static int +ble_ll_ctrl_rx_conn_update(struct ble_ll_conn_sm *connsm, uint8_t *dptr) +{ + uint8_t rsp_opcode; + uint16_t conn_events; + struct ble_ll_conn_upd_req *reqdata; + + /* Only a slave should receive this */ + if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + return BLE_LL_CTRL_UNKNOWN_RSP; + } + + /* Retrieve parameters */ + reqdata = &connsm->conn_update_req; + reqdata->winsize = dptr[0]; + reqdata->winoffset = get_le16(dptr + 1); + reqdata->interval = get_le16(dptr + 3); + reqdata->latency = get_le16(dptr + 5); + reqdata->timeout = get_le16(dptr + 7); + reqdata->instant = get_le16(dptr + 9); + + /* XXX: validate them at some point. If they dont check out, we + return the unknown response */ + rsp_opcode = BLE_ERR_MAX; + + /* If instant is in the past, we have to end the connection */ + conn_events = (reqdata->instant - connsm->event_cntr) & 0xFFFF; + if (conn_events >= 32767) { + ble_ll_conn_timeout(connsm, BLE_ERR_INSTANT_PASSED); + } else { + connsm->csmflags.cfbit.conn_update_sched = 1; + + /* + * Errata says that receiving a connection update when the event + * counter is equal to the instant means wesimply ignore the window + * offset and window size. Anchor point has already been set based on + * first packet received in connection event. Given that we increment + * the event counter BEFORE checking to see if the instant is equal to + * the event counter what we do here is increment the instant and set + * the window offset and size to 0. + */ + if (conn_events == 0) { + reqdata->winoffset = 0; + reqdata->winsize = 0; + reqdata->instant += 1; + } + } + + return rsp_opcode; +} + +void +ble_ll_ctrl_initiate_dle(struct ble_ll_conn_sm *connsm) +{ + if (!(connsm->conn_features & BLE_LL_FEAT_DATA_LEN_EXT)) { + return; + } + + /* + * Section 4.5.10 Vol 6 PART B. If the max tx/rx time or octets + * exceeds the minimum, data length procedure needs to occur + */ + if ((connsm->max_tx_octets <= BLE_LL_CONN_SUPP_BYTES_MIN) && + (connsm->max_rx_octets <= BLE_LL_CONN_SUPP_BYTES_MIN) && + (connsm->max_tx_time <= BLE_LL_CONN_SUPP_TIME_MIN) && + (connsm->max_rx_time <= BLE_LL_CONN_SUPP_TIME_MIN)) { + return; + } + + ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD); +} + +static void +ble_ll_ctrl_update_features(struct ble_ll_conn_sm *connsm, uint8_t *feat) +{ + connsm->conn_features = feat[0]; + memcpy(connsm->remote_features, feat + 1, 7); + + /* If we received peer's features for the 1st time, we should try DLE */ + if (!connsm->csmflags.cfbit.rxd_features) { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + /* + * If connection was established on uncoded PHY, by default we use + * MaxTxTime and MaxRxTime applicable for that PHY since we are not + * allowed to indicate longer supported time if peer does not support + * LE Coded PHY. However, once we know that peer does support it we can + * update those values to ones applicable for coded PHY. + */ + if (connsm->remote_features[0] & (BLE_LL_FEAT_LE_CODED_PHY >> 8)) { + if (connsm->host_req_max_tx_time) { + connsm->max_tx_time = max(connsm->max_tx_time, + connsm->host_req_max_tx_time); + } else { + connsm->max_tx_time = g_ble_ll_conn_params.conn_init_max_tx_time_coded; + } + connsm->max_rx_time = BLE_LL_CONN_SUPP_TIME_MAX_CODED; + } +#endif + + connsm->csmflags.cfbit.pending_initiate_dle = 1; + connsm->csmflags.cfbit.rxd_features = 1; + } +} + +/** + * Called when we receive a feature request or a slave initiated feature + * request. + * + * + * @param connsm + * @param dptr + * @param rspbuf + * @param opcode + * @param new_features + * + * @return int + */ +static int +ble_ll_ctrl_rx_feature_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr, + uint8_t *rspbuf, uint8_t opcode) +{ + uint8_t rsp_opcode; + uint64_t our_feat; + + /* + * Only accept slave feature requests if we are a master and feature + * requests if we are a slave. + */ + if (opcode == BLE_LL_CTRL_SLAVE_FEATURE_REQ) { + if (connsm->conn_role != BLE_LL_CONN_ROLE_MASTER) { + return BLE_LL_CTRL_UNKNOWN_RSP; + } + } else { + /* XXX: not sure this is correct but do it anyway */ + if (connsm->conn_role != BLE_LL_CONN_ROLE_SLAVE) { + return BLE_LL_CTRL_UNKNOWN_RSP; + } + } + + our_feat = ble_ll_read_supp_features(); + + rsp_opcode = BLE_LL_CTRL_FEATURE_RSP; + + ble_ll_ctrl_update_features(connsm, dptr); + + /* + * 1st octet of features should be common features of local and remote + * controller - we call this 'connection features' + * remaining octets are features of controller which sends PDU, in this case + * it's our controller + * + * See: Vol 6, Part B, section 2.4.2.10 + */ + connsm->conn_features &= our_feat; + + put_le64(rspbuf + 1, our_feat); + rspbuf[1] = connsm->conn_features; + + return rsp_opcode; +} + +/** + * Called when we receive a feature response + * + * @param connsm + * @param dptr + * @param new_features + * + */ +static void +ble_ll_ctrl_rx_feature_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr) +{ + ble_ll_ctrl_update_features(connsm, dptr); + + /* Stop the control procedure */ + if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG)) { + ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG); + } + + /* Send event to host if pending features read */ + if (connsm->csmflags.cfbit.pending_hci_rd_features) { + ble_ll_hci_ev_rd_rem_used_feat(connsm, BLE_ERR_SUCCESS); + connsm->csmflags.cfbit.pending_hci_rd_features = 0; + } +} + +/** + * + * + * Context: Link Layer task + * + * @param connsm + * @param dptr + * @param rspbuf + * + * @return int + */ +static int +ble_ll_ctrl_rx_conn_param_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr, + uint8_t *rspbuf) +{ + uint8_t rsp_opcode; + + /* + * This is not in the specification per se but it simplifies the + * implementation. If we get a connection parameter request and we + * are awaiting a reply from the host, simply ignore the request. This + * might not be a good idea if the parameters are different, but oh + * well. This is not expected to happen anyway. A return of BLE_ERR_MAX + * means that we will simply discard the connection parameter request + */ + if (connsm->csmflags.cfbit.awaiting_host_reply) { + return BLE_ERR_MAX; + } + + /* XXX: remember to deal with this on the master: if the slave has + * initiated a procedure we may have received its connection parameter + * update request and have signaled the host with an event. If that + * is the case, we will need to drop the host command when we get it + and also clear any applicable states. */ + + /* XXX: Read 5.3 again. There are multiple control procedures that might + * be pending (a connection update) that will cause collisions and the + behavior below. */ + /* + * Check for procedure collision (Vol 6 PartB 5.3). If we are a slave + * and we receive a request we "consider the slave initiated + * procedure as complete". This means send a connection update complete + * event (with error). + * + * If a master, we send reject with a + * transaction collision error code. + */ + if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ)) { + if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { + ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ); + ble_ll_hci_ev_conn_update(connsm, BLE_ERR_LMP_COLLISION); + } else { + /* The master sends reject ind ext w/error code 0x23 */ + rsp_opcode = BLE_LL_CTRL_REJECT_IND_EXT; + rspbuf[1] = BLE_LL_CTRL_CONN_PARM_REQ; + rspbuf[2] = BLE_ERR_LMP_COLLISION; + return rsp_opcode; + } + } + + /* + * If we are a master and we currently performing a channel map + * update procedure we need to return an error + */ + if ((connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) && + (connsm->csmflags.cfbit.chanmap_update_scheduled)) { + rsp_opcode = BLE_LL_CTRL_REJECT_IND_EXT; + rspbuf[1] = BLE_LL_CTRL_CONN_PARM_REQ; + rspbuf[2] = BLE_ERR_DIFF_TRANS_COLL; + return rsp_opcode; + } + + /* Process the received connection parameter request */ + rsp_opcode = ble_ll_ctrl_conn_param_pdu_proc(connsm, dptr, rspbuf, + BLE_LL_CTRL_CONN_PARM_REQ); + return rsp_opcode; +} + +static int +ble_ll_ctrl_rx_conn_param_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr, + uint8_t *rspbuf) +{ + uint8_t rsp_opcode; + + /* A slave should never receive this response */ + if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { + return BLE_LL_CTRL_UNKNOWN_RSP; + } + + /* + * This case should never happen! It means that the slave initiated a + * procedure and the master initiated one as well. If we do get in this + * state just clear the awaiting reply. The slave will hopefully stop its + * procedure when we reply. + */ + if (connsm->csmflags.cfbit.awaiting_host_reply) { + connsm->csmflags.cfbit.awaiting_host_reply = 0; + } + + /* If we receive a response and no procedure is pending, just leave */ + if (!IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ)) { + return BLE_ERR_MAX; + } + + /* Process the received connection parameter response */ + rsp_opcode = ble_ll_ctrl_conn_param_pdu_proc(connsm, dptr, rspbuf, + BLE_LL_CTRL_CONN_PARM_RSP); + return rsp_opcode; +} + +/** + * Called to process the LL control PDU VERSION_IND + * + * Context: Link Layer task + * + * @param connsm + * @param dptr + * @param rspbuf + * + * @return int + */ +static int +ble_ll_ctrl_rx_version_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr, + uint8_t *rspbuf) +{ + uint8_t rsp_opcode; + + /* Process the packet */ + connsm->vers_nr = dptr[0]; + connsm->comp_id = get_le16(dptr + 1); + connsm->sub_vers_nr = get_le16(dptr + 3); + connsm->csmflags.cfbit.rxd_version_ind = 1; + + rsp_opcode = BLE_ERR_MAX; + if (!connsm->csmflags.cfbit.version_ind_sent) { + rsp_opcode = BLE_LL_CTRL_VERSION_IND; + ble_ll_ctrl_version_ind_make(connsm, rspbuf); + } + + /* Stop the control procedure */ + if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_VERSION_XCHG)) { + ble_ll_hci_ev_rd_rem_ver(connsm, BLE_ERR_SUCCESS); + ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_VERSION_XCHG); + } + return rsp_opcode; +} + +/** + * Called to process a received channel map request control pdu. + * + * Context: Link Layer task + * + * @param connsm + * @param dptr + */ +static int +ble_ll_ctrl_rx_chanmap_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr) +{ + uint16_t instant; + uint16_t conn_events; + + if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + return BLE_LL_CTRL_UNKNOWN_RSP; + } + + /* If instant is in the past, we have to end the connection */ + instant = get_le16(dptr + BLE_LL_CONN_CHMAP_LEN); + conn_events = (instant - connsm->event_cntr) & 0xFFFF; + if (conn_events >= 32767) { + ble_ll_conn_timeout(connsm, BLE_ERR_INSTANT_PASSED); + } else { + connsm->chanmap_instant = instant; + memcpy(connsm->req_chanmap, dptr, BLE_LL_CONN_CHMAP_LEN); + connsm->csmflags.cfbit.chanmap_update_scheduled = 1; + } + + return BLE_ERR_MAX; +} + +/** + * Initiate LL control procedure. + * + * This function is called to obtain a mbuf to send a LL control PDU. The data + * channel PDU header is not part of the mbuf data; it is part of the BLE + * header (which is part of the mbuf). + * + * Context: LL task. + * + * @param connsm + * @param ctrl_proc + */ +static struct os_mbuf * +ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc) +{ + uint8_t len; + uint8_t opcode; + uint8_t *dptr; + uint8_t *ctrdata; + struct os_mbuf *om; + + /* Get an mbuf for the control pdu */ + om = os_msys_get_pkthdr(BLE_LL_CTRL_MAX_PDU_LEN, sizeof(struct ble_mbuf_hdr)); + + if (om) { + /* The control data starts after the opcode (1 byte) */ + dptr = om->om_data; + ctrdata = dptr + 1; + + switch (ctrl_proc) { + case BLE_LL_CTRL_PROC_CONN_UPDATE: + opcode = BLE_LL_CTRL_CONN_UPDATE_IND; + ble_ll_ctrl_conn_upd_make(connsm, ctrdata, NULL); + break; + case BLE_LL_CTRL_PROC_CHAN_MAP_UPD: + opcode = BLE_LL_CTRL_CHANNEL_MAP_REQ; + ble_ll_ctrl_chanmap_req_make(connsm, ctrdata); + break; + case BLE_LL_CTRL_PROC_FEATURE_XCHG: + if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + opcode = BLE_LL_CTRL_FEATURE_REQ; + } else { + opcode = BLE_LL_CTRL_SLAVE_FEATURE_REQ; + } + put_le64(ctrdata, ble_ll_read_supp_features()); + break; + case BLE_LL_CTRL_PROC_VERSION_XCHG: + opcode = BLE_LL_CTRL_VERSION_IND; + ble_ll_ctrl_version_ind_make(connsm, ctrdata); + break; + case BLE_LL_CTRL_PROC_TERMINATE: + opcode = BLE_LL_CTRL_TERMINATE_IND; + ctrdata[0] = connsm->disconnect_reason; + break; + case BLE_LL_CTRL_PROC_CONN_PARAM_REQ: + opcode = BLE_LL_CTRL_CONN_PARM_REQ; + ble_ll_ctrl_conn_param_pdu_make(connsm, ctrdata, NULL); + break; + case BLE_LL_CTRL_PROC_LE_PING: + opcode = BLE_LL_CTRL_PING_REQ; + break; + case BLE_LL_CTRL_PROC_DATA_LEN_UPD: + opcode = BLE_LL_CTRL_LENGTH_REQ; + ble_ll_ctrl_datalen_upd_make(connsm, dptr); + break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + /* XXX: deal with already encrypted connection.*/ + case BLE_LL_CTRL_PROC_ENCRYPT: + /* If we are already encrypted we do pause procedure */ + if (connsm->enc_data.enc_state == CONN_ENC_S_ENCRYPTED) { + opcode = BLE_LL_CTRL_PAUSE_ENC_REQ; + } else { + opcode = BLE_LL_CTRL_ENC_REQ; + ble_ll_ctrl_enc_req_make(connsm, ctrdata); + } + break; +#endif +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + case BLE_LL_CTRL_PROC_PHY_UPDATE: + opcode = BLE_LL_CTRL_PHY_REQ; + ble_ll_ctrl_phy_req_rsp_make(connsm, ctrdata); + break; +#endif + default: + BLE_LL_ASSERT(0); + break; + } + + /* Set llid, length and opcode */ + dptr[0] = opcode; + len = g_ble_ll_ctrl_pkt_lengths[opcode] + 1; + + /* Add packet to transmit queue of connection */ + ble_ll_conn_enqueue_pkt(connsm, om, BLE_LL_LLID_CTRL, len); + } + + return om; +} + +/** + * Called to determine if the pdu is a TERMINATE_IND + * + * @param hdr + * @param opcode + * + * @return int + */ +int +ble_ll_ctrl_is_terminate_ind(uint8_t hdr, uint8_t opcode) +{ + int rc; + + rc = 0; + if ((hdr & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_CTRL) { + if (opcode == BLE_LL_CTRL_TERMINATE_IND) { + rc = 1; + } + } + return rc; +} + +/** + * Stops the LL control procedure indicated by 'ctrl_proc'. + * + * Context: Link Layer task + * + * @param connsm + * @param ctrl_proc + */ +void +ble_ll_ctrl_proc_stop(struct ble_ll_conn_sm *connsm, int ctrl_proc) +{ + if (connsm->cur_ctrl_proc == ctrl_proc) { + ble_npl_callout_stop(&connsm->ctrl_proc_rsp_timer); + connsm->cur_ctrl_proc = BLE_LL_CTRL_PROC_IDLE; + } + CLR_PENDING_CTRL_PROC(connsm, ctrl_proc); + + /* If there are others, start them */ + ble_ll_ctrl_chk_proc_start(connsm); +} + +/** + * Called to start the terminate procedure. + * + * Context: Link Layer task. + * + * @param connsm + */ +void +ble_ll_ctrl_terminate_start(struct ble_ll_conn_sm *connsm) +{ + int ctrl_proc; + uint32_t usecs; + struct os_mbuf *om; + + BLE_LL_ASSERT(connsm->disconnect_reason != 0); + + ctrl_proc = BLE_LL_CTRL_PROC_TERMINATE; + om = ble_ll_ctrl_proc_init(connsm, ctrl_proc); + if (om) { + CONN_F_TERMINATE_STARTED(connsm) = 1; + + /* Set terminate "timeout" */ + usecs = connsm->supervision_tmo * BLE_HCI_CONN_SPVN_TMO_UNITS * 1000; + connsm->terminate_timeout = os_cputime_get32() + + os_cputime_usecs_to_ticks(usecs); + } +} + +/** + * Called to start a LL control procedure except for the terminate procedure. We + * always set the control procedure pending bit even if the control procedure + * has been initiated. + * + * Context: Link Layer task. + * + * @param connsm Pointer to connection state machine. + */ +void +ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc) +{ + struct os_mbuf *om; + + BLE_LL_ASSERT(ctrl_proc != BLE_LL_CTRL_PROC_TERMINATE); + + om = NULL; + if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_IDLE) { + /* Initiate the control procedure. */ + om = ble_ll_ctrl_proc_init(connsm, ctrl_proc); + if (om) { + /* Set the current control procedure */ + connsm->cur_ctrl_proc = ctrl_proc; + + /* Initialize the procedure response timeout */ + if (ctrl_proc != BLE_LL_CTRL_PROC_CHAN_MAP_UPD) { + ble_ll_ctrl_start_rsp_timer(connsm); + } + } + } + + /* Set bitmask denoting control procedure is pending */ + connsm->pending_ctrl_procs |= (1 << ctrl_proc); +} + +/** + * Called to determine if we need to start a LL control procedure for the given + * connection. + * + * Context: Link Layer + * + * @param connsm Pointer to connection state machine. + */ +void +ble_ll_ctrl_chk_proc_start(struct ble_ll_conn_sm *connsm) +{ + int i; + + /* XXX: TODO new rules! Cannot start certain control procedures if other + * ones are peer initiated. We need to wait. Deal with this. + */ + + /* + * If we are terminating, dont start any new procedures but start + * terminate if needed + */ + if (connsm->disconnect_reason) { + if (!CONN_F_TERMINATE_STARTED(connsm)) { + /* + * If the terminate procedure has not started it means we were not + * able to start it right away (no control pdu was available). + * Start it now. No need to start any other procedures. + */ + ble_ll_ctrl_terminate_start(connsm); + } + return; + } + + /* If there is a running procedure or no pending, do nothing */ + if ((connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_IDLE) && + (connsm->pending_ctrl_procs != 0)) { + /* + * The specification says there is no priority to control procedures + * so just start from the first one for now. + */ + for (i = 0; i < BLE_LL_CTRL_PROC_NUM; ++i) { + if (IS_PENDING_CTRL_PROC(connsm, i)) { + /* + * The version exchange is a special case. If we have already + * received the information dont start it. + */ + if ((i == BLE_LL_CTRL_PROC_VERSION_XCHG) && + (connsm->csmflags.cfbit.rxd_version_ind)) { + ble_ll_hci_ev_rd_rem_ver(connsm, BLE_ERR_SUCCESS); + CLR_PENDING_CTRL_PROC(connsm, i); + } else { + ble_ll_ctrl_proc_start(connsm, i); + break; + } + } + } + } +} + +/** + * Called when the Link Layer receives a LL control PDU. + * + * NOTE: this function uses the received PDU for the response in some cases. If + * the received PDU is not used it needs to be freed here. + * + * XXX: may want to check, for both master and slave, whether the control + * pdu should be received by that role. Might make for less code... + * Context: Link Layer + * + * @param om + * @param connsm + */ +int +ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om) +{ + uint32_t features; + uint32_t feature; + uint8_t len; + uint8_t opcode; + uint8_t rsp_opcode; + uint8_t *dptr; + uint8_t *rspbuf; + uint8_t *rspdata; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + int restart_encryption; +#endif + int rc = 0; + + /* XXX: where do we validate length received and packet header length? + * do this in LL task when received. Someplace!!! What I mean + * is we should validate the over the air length with the mbuf length. + Should the PHY do that???? */ + + /* + * dptr points to om_data pointer. The first byte of om_data is the + * first byte of the Data Channel PDU header. Get length from header and + * opcode from LL control PDU. + */ + dptr = om->om_data; + len = dptr[1]; + opcode = dptr[2]; + + /* + * rspbuf points to first byte of response. The response buffer does not + * contain the Data Channel PDU. Thus, the first byte of rspbuf is the + * LL control PDU payload (the opcode of the control PDU). rspdata + * points to CtrData in the control PDU. + */ + rspbuf = dptr; + rspdata = rspbuf + 1; + + /* Move data pointer to start of control data (2 byte PDU hdr + opcode) */ + dptr += (BLE_LL_PDU_HDR_LEN + 1); + + /* + * Subtract the opcode from the length. Note that if the length was zero, + * which would be an error, we will fail the check against the length + * of the control packet. + */ + --len; + + ble_ll_trace_u32x2(BLE_LL_TRACE_ID_CTRL_RX, opcode, len); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + restart_encryption = 0; +#endif + + /* If opcode comes from reserved value or CtrlData fields is invalid + * we shall respond with LL_UNKNOWN_RSP + */ + if ((opcode >= BLE_LL_CTRL_OPCODES) || + (len != g_ble_ll_ctrl_pkt_lengths[opcode])) { + rc = -1; + rsp_opcode = BLE_LL_CTRL_UNKNOWN_RSP; + goto ll_ctrl_send_rsp; + } + + /* Check if the feature is supported. */ + switch (opcode) { + case BLE_LL_CTRL_LENGTH_REQ: + feature = BLE_LL_FEAT_DATA_LEN_EXT; + break; + case BLE_LL_CTRL_SLAVE_FEATURE_REQ: + feature = BLE_LL_FEAT_SLAVE_INIT; + break; + case BLE_LL_CTRL_CONN_PARM_REQ: + case BLE_LL_CTRL_CONN_PARM_RSP: + feature = BLE_LL_FEAT_CONN_PARM_REQ; + break; + case BLE_LL_CTRL_ENC_REQ: + case BLE_LL_CTRL_START_ENC_REQ: + case BLE_LL_CTRL_PAUSE_ENC_REQ: + feature = BLE_LL_FEAT_LE_ENCRYPTION; + break; + case BLE_LL_CTRL_PING_REQ: + feature = BLE_LL_FEAT_LE_PING; + break; + case BLE_LL_CTRL_PHY_REQ: + feature = BLE_LL_FEAT_LE_2M_PHY | BLE_LL_FEAT_LE_CODED_PHY; + break; + case BLE_LL_CTRL_MIN_USED_CHAN_IND: + feature = BLE_LL_FEAT_MIN_USED_CHAN; + break; + case BLE_LL_CTRL_PERIODIC_SYNC_IND: + feature = BLE_LL_FEAT_SYNC_TRANS_RECV; + break; + default: + feature = 0; + break; + } + + if (feature) { + features = ble_ll_read_supp_features(); + if ((features & feature) == 0) { + if (opcode == BLE_LL_CTRL_ENC_REQ) { + if (connsm->conn_features & BLE_LL_FEAT_EXTENDED_REJ) { + rsp_opcode = BLE_LL_CTRL_REJECT_IND_EXT; + rspbuf[1] = opcode; + rspbuf[2] = BLE_ERR_UNSUPP_REM_FEATURE; + + } else { + rsp_opcode = BLE_LL_CTRL_REJECT_IND; + rspbuf[1] = BLE_ERR_UNSUPP_REM_FEATURE; + } + } else { + /* Construct unknown rsp pdu */ + rsp_opcode = BLE_LL_CTRL_UNKNOWN_RSP; + } + goto ll_ctrl_send_rsp; + } + } + + /* Process opcode */ + rsp_opcode = BLE_ERR_MAX; + switch (opcode) { + case BLE_LL_CTRL_CONN_UPDATE_IND: + rsp_opcode = ble_ll_ctrl_rx_conn_update(connsm, dptr); + break; + case BLE_LL_CTRL_CHANNEL_MAP_REQ: + rsp_opcode = ble_ll_ctrl_rx_chanmap_req(connsm, dptr); + break; + case BLE_LL_CTRL_LENGTH_REQ: + /* Extract parameters and check if valid */ + if (ble_ll_ctrl_len_proc(connsm, dptr)) { + rc = -1; + rsp_opcode = BLE_LL_CTRL_UNKNOWN_RSP; + goto ll_ctrl_send_rsp; + } + + /* + * If we have not started this procedure ourselves and it is + * pending, no need to perform it. + */ + if ((connsm->cur_ctrl_proc != BLE_LL_CTRL_PROC_DATA_LEN_UPD) && + IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD)) { + CLR_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD); + } + + /* Send a response */ + rsp_opcode = BLE_LL_CTRL_LENGTH_RSP; + ble_ll_ctrl_datalen_upd_make(connsm, rspbuf); + break; + case BLE_LL_CTRL_LENGTH_RSP: + /* According to specification, process this only if we asked for it. */ + if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_DATA_LEN_UPD) { + /* + * Process the received data. If received data is invalid, we'll + * reply with LL_UNKNOWN_RSP as per spec, but we still need to stop + * control procedure to avoid timeout. + */ + if (ble_ll_ctrl_len_proc(connsm, dptr)) { + rc = -1; + rsp_opcode = BLE_LL_CTRL_UNKNOWN_RSP; + } + + /* Stop the control procedure */ + ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD); + } + break; + case BLE_LL_CTRL_UNKNOWN_RSP: + rsp_opcode = ble_ll_ctrl_proc_unk_rsp(connsm, dptr, rspdata); + break; + case BLE_LL_CTRL_FEATURE_REQ: + rsp_opcode = ble_ll_ctrl_rx_feature_req(connsm, dptr, rspbuf, opcode); + break; + /* XXX: check to see if ctrl procedure was running? Do we care? */ + case BLE_LL_CTRL_FEATURE_RSP: + ble_ll_ctrl_rx_feature_rsp(connsm, dptr); + break; + case BLE_LL_CTRL_VERSION_IND: + rsp_opcode = ble_ll_ctrl_rx_version_ind(connsm, dptr, rspdata); + break; + case BLE_LL_CTRL_SLAVE_FEATURE_REQ: + rsp_opcode = ble_ll_ctrl_rx_feature_req(connsm, dptr, rspbuf, opcode); + break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + case BLE_LL_CTRL_ENC_REQ: + rsp_opcode = ble_ll_ctrl_rx_enc_req(connsm, dptr, rspdata); + break; + case BLE_LL_CTRL_ENC_RSP: + ble_ll_ctrl_rx_enc_rsp(connsm, dptr); + break; + case BLE_LL_CTRL_START_ENC_REQ: + rsp_opcode = ble_ll_ctrl_rx_start_enc_req(connsm); + break; + case BLE_LL_CTRL_START_ENC_RSP: + rsp_opcode = ble_ll_ctrl_rx_start_enc_rsp(connsm); + break; + case BLE_LL_CTRL_PAUSE_ENC_REQ: + rsp_opcode = ble_ll_ctrl_rx_pause_enc_req(connsm); + break; + case BLE_LL_CTRL_PAUSE_ENC_RSP: + rsp_opcode = ble_ll_ctrl_rx_pause_enc_rsp(connsm); + if (rsp_opcode == BLE_LL_CTRL_PAUSE_ENC_RSP) { + restart_encryption = 1; + } + break; +#endif + case BLE_LL_CTRL_PING_REQ: + rsp_opcode = BLE_LL_CTRL_PING_RSP; + break; + case BLE_LL_CTRL_PING_RSP: + ble_ll_ctrl_rx_ping_rsp(connsm); + break; + case BLE_LL_CTRL_CONN_PARM_REQ: + rsp_opcode = ble_ll_ctrl_rx_conn_param_req(connsm, dptr, rspbuf); + break; + case BLE_LL_CTRL_CONN_PARM_RSP: + rsp_opcode = ble_ll_ctrl_rx_conn_param_rsp(connsm, dptr, rspbuf); + break; + /* Fall-through intentional... */ + case BLE_LL_CTRL_REJECT_IND: + case BLE_LL_CTRL_REJECT_IND_EXT: + /* Sometimes reject triggers sending other LL CTRL msg */ + rsp_opcode = ble_ll_ctrl_rx_reject_ind(connsm, dptr, opcode, rspdata); + break; +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + case BLE_LL_CTRL_PHY_REQ: + rsp_opcode = ble_ll_ctrl_rx_phy_req(connsm, dptr, rspdata); + break; + case BLE_LL_CTRL_PHY_RSP: + rsp_opcode = ble_ll_ctrl_rx_phy_rsp(connsm, dptr, rspdata); + break; + case BLE_LL_CTRL_PHY_UPDATE_IND: + rsp_opcode = ble_ll_ctrl_rx_phy_update_ind(connsm, dptr); + break; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) + case BLE_LL_CTRL_PERIODIC_SYNC_IND: + rsp_opcode = ble_ll_ctrl_rx_periodic_sync_ind(connsm, dptr); + break; +#endif + default: + /* Nothing to do here */ + break; + } + + /* Free mbuf or send response */ +ll_ctrl_send_rsp: + if (rsp_opcode == BLE_ERR_MAX) { + os_mbuf_free_chain(om); + } else { + /* + * Write the response opcode into the buffer. If this is an unknown + * response, put opcode of unknown pdu into buffer. + */ + rspbuf[0] = rsp_opcode; + if (rsp_opcode == BLE_LL_CTRL_UNKNOWN_RSP) { + rspbuf[1] = opcode; + } + len = g_ble_ll_ctrl_pkt_lengths[rsp_opcode] + 1; + ble_ll_conn_enqueue_pkt(connsm, om, BLE_LL_LLID_CTRL, len); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + if (restart_encryption) { + /* XXX: what happens if this fails? Meaning we cant allocate + mbuf? */ + ble_ll_ctrl_proc_init(connsm, BLE_LL_CTRL_PROC_ENCRYPT); + } +#endif + } + + if (connsm->csmflags.cfbit.pending_initiate_dle) { + connsm->csmflags.cfbit.pending_initiate_dle = 0; + ble_ll_ctrl_initiate_dle(connsm); + } + + return rc; +} + +/** + * Called to create and send a REJECT_IND_EXT control PDU or a REJECT_IND + * + * @param connsm + * @param rej_opcode + * @param err + * + * @return int + */ +int +ble_ll_ctrl_reject_ind_send(struct ble_ll_conn_sm *connsm, uint8_t rej_opcode, + uint8_t err) +{ + int rc; + uint8_t len; + uint8_t opcode; + uint8_t *rspbuf; + struct os_mbuf *om; + + om = os_msys_get_pkthdr(BLE_LL_CTRL_MAX_PDU_LEN, + sizeof(struct ble_mbuf_hdr)); + if (om) { + rspbuf = om->om_data; + opcode = BLE_LL_CTRL_REJECT_IND_EXT; + if (rej_opcode == BLE_LL_CTRL_ENC_REQ) { + if ((connsm->conn_features & BLE_LL_FEAT_EXTENDED_REJ) == 0) { + opcode = BLE_LL_CTRL_REJECT_IND; + } + } + rspbuf[0] = opcode; + if (opcode == BLE_LL_CTRL_REJECT_IND) { + rspbuf[1] = err; + len = BLE_LL_CTRL_REJ_IND_LEN + 1; + } else { + rspbuf[1] = rej_opcode; + rspbuf[2] = err; + len = BLE_LL_CTRL_REJECT_IND_EXT_LEN + 1; + } + ble_ll_conn_enqueue_pkt(connsm, om, BLE_LL_LLID_CTRL, len); + rc = 0; + } else { + rc = 1; + } + return rc; +} + +/** + * Called when a Link Layer Control pdu has been transmitted successfully. + * This is called when we have a received a PDU during the ISR. + * + * Context: ISR + * + * @param txpdu + * + * @return int + */ +int +ble_ll_ctrl_tx_done(struct os_mbuf *txpdu, struct ble_ll_conn_sm *connsm) +{ + int rc; + uint8_t opcode; + + rc = 0; + opcode = txpdu->om_data[0]; + switch (opcode) { + case BLE_LL_CTRL_TERMINATE_IND: + connsm->csmflags.cfbit.terminate_ind_txd = 1; + rc = -1; + break; + case BLE_LL_CTRL_REJECT_IND_EXT: + if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_CONN_PARAM_REQ) { + /* If rejecting opcode is BLE_LL_CTRL_PROC_CONN_PARAM_REQ and + * reason is LMP collision that means we are master on the link and + * peer wanted to start procedure which we already started. + * Let's wait for response and do not close procedure. */ + if (txpdu->om_data[1] == BLE_LL_CTRL_CONN_PARM_REQ && + txpdu->om_data[2] != BLE_ERR_LMP_COLLISION) { + connsm->reject_reason = txpdu->om_data[2]; + connsm->csmflags.cfbit.host_expects_upd_event = 1; + } + } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + if (connsm->enc_data.enc_state > CONN_ENC_S_ENCRYPTED) { + connsm->enc_data.enc_state = CONN_ENC_S_UNENCRYPTED; + } +#endif + break; + case BLE_LL_CTRL_REJECT_IND: +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + connsm->enc_data.enc_state = CONN_ENC_S_UNENCRYPTED; +#endif + break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + case BLE_LL_CTRL_PAUSE_ENC_REQ: + /* note: fall-through intentional */ + case BLE_LL_CTRL_ENC_REQ: + connsm->enc_data.enc_state = CONN_ENC_S_ENC_RSP_WAIT; + break; + case BLE_LL_CTRL_ENC_RSP: + connsm->csmflags.cfbit.send_ltk_req = 1; + break; + case BLE_LL_CTRL_START_ENC_RSP: + if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { + connsm->enc_data.enc_state = CONN_ENC_S_ENCRYPTED; + if (CONN_F_LE_PING_SUPP(connsm)) { + ble_ll_conn_auth_pyld_timer_start(connsm); + } + } + break; + case BLE_LL_CTRL_PAUSE_ENC_RSP: + if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { + connsm->enc_data.enc_state = CONN_ENC_S_PAUSE_ENC_RSP_WAIT; + } + break; +#endif +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + case BLE_LL_CTRL_PHY_REQ: + connsm->phy_tx_transition = + ble_ll_ctrl_phy_tx_transition_get(connsm->phy_data.req_pref_tx_phys_mask); + break; + case BLE_LL_CTRL_PHY_UPDATE_IND: + connsm->phy_tx_transition = + ble_ll_ctrl_phy_tx_transition_get(txpdu->om_data[2]); + break; +#endif + default: + break; + } + + os_mbuf_free_chain(txpdu); + return rc; +} +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_dtm.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_dtm.c new file mode 100644 index 000000000..baf8c2570 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_dtm.c @@ -0,0 +1,728 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef ESP_PLATFORM + +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/sysinit/sysinit.h" + +#if MYNEWT_VAL(BLE_LL_DTM) + +#include +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/nimble/porting/nimble/include/stats/stats.h" +#include "../include/controller/ble_ll.h" +#include "../include/controller/ble_phy.h" +#include "../include/controller/ble_ll_sched.h" +#include "../include/controller/ble_ll_rfmgmt.h" +#include "ble_ll_dtm_priv.h" + +STATS_SECT_START(ble_ll_dtm_stats) + STATS_SECT_ENTRY(rx_count) + STATS_SECT_ENTRY(tx_failed) + STATS_SECT_ENTRY(rx_failed) +STATS_SECT_END +STATS_SECT_DECL(ble_ll_dtm_stats) ble_ll_dtm_stats; + +STATS_NAME_START(ble_ll_dtm_stats) + STATS_NAME(ble_ll_dtm_stats, rx_count) + STATS_NAME(ble_ll_dtm_stats, tx_failed) + STATS_NAME(ble_ll_dtm_stats, rx_failed) +STATS_NAME_END(ble_phy_stats) + +struct dtm_ctx { + uint8_t payload_packet; + uint8_t itvl_rem_usec; + uint16_t num_of_packets; + uint32_t itvl_ticks; +#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS) + uint16_t num_of_packets_max; +#endif + int active; + uint8_t rf_channel; + uint8_t phy_mode; + struct os_mbuf *om; + struct ble_npl_event evt; + struct ble_ll_sched_item sch; + uint32_t pdu_start_ticks; + uint8_t pdu_start_usecs; +}; + +static struct dtm_ctx g_ble_ll_dtm_ctx; + +static const uint8_t g_ble_ll_dtm_prbs9_data[] = +{ + 0xff, 0xc1, 0xfb, 0xe8, 0x4c, 0x90, 0x72, 0x8b, + 0xe7, 0xb3, 0x51, 0x89, 0x63, 0xab, 0x23, 0x23, + 0x02, 0x84, 0x18, 0x72, 0xaa, 0x61, 0x2f, 0x3b, + 0x51, 0xa8, 0xe5, 0x37, 0x49, 0xfb, 0xc9, 0xca, + 0x0c, 0x18, 0x53, 0x2c, 0xfd, 0x45, 0xe3, 0x9a, + 0xe6, 0xf1, 0x5d, 0xb0, 0xb6, 0x1b, 0xb4, 0xbe, + 0x2a, 0x50, 0xea, 0xe9, 0x0e, 0x9c, 0x4b, 0x5e, + 0x57, 0x24, 0xcc, 0xa1, 0xb7, 0x59, 0xb8, 0x87, + 0xff, 0xe0, 0x7d, 0x74, 0x26, 0x48, 0xb9, 0xc5, + 0xf3, 0xd9, 0xa8, 0xc4, 0xb1, 0xd5, 0x91, 0x11, + 0x01, 0x42, 0x0c, 0x39, 0xd5, 0xb0, 0x97, 0x9d, + 0x28, 0xd4, 0xf2, 0x9b, 0xa4, 0xfd, 0x64, 0x65, + 0x06, 0x8c, 0x29, 0x96, 0xfe, 0xa2, 0x71, 0x4d, + 0xf3, 0xf8, 0x2e, 0x58, 0xdb, 0x0d, 0x5a, 0x5f, + 0x15, 0x28, 0xf5, 0x74, 0x07, 0xce, 0x25, 0xaf, + 0x2b, 0x12, 0xe6, 0xd0, 0xdb, 0x2c, 0xdc, 0xc3, + 0x7f, 0xf0, 0x3e, 0x3a, 0x13, 0xa4, 0xdc, 0xe2, + 0xf9, 0x6c, 0x54, 0xe2, 0xd8, 0xea, 0xc8, 0x88, + 0x00, 0x21, 0x86, 0x9c, 0x6a, 0xd8, 0xcb, 0x4e, + 0x14, 0x6a, 0xf9, 0x4d, 0xd2, 0x7e, 0xb2, 0x32, + 0x03, 0xc6, 0x14, 0x4b, 0x7f, 0xd1, 0xb8, 0xa6, + 0x79, 0x7c, 0x17, 0xac, 0xed, 0x06, 0xad, 0xaf, + 0x0a, 0x94, 0x7a, 0xba, 0x03, 0xe7, 0x92, 0xd7, + 0x15, 0x09, 0x73, 0xe8, 0x6d, 0x16, 0xee, 0xe1, + 0x3f, 0x78, 0x1f, 0x9d, 0x09, 0x52, 0x6e, 0xf1, + 0x7c, 0x36, 0x2a, 0x71, 0x6c, 0x75, 0x64, 0x44, + 0x80, 0x10, 0x43, 0x4e, 0x35, 0xec, 0x65, 0x27, + 0x0a, 0xb5, 0xfc, 0x26, 0x69, 0x3f, 0x59, 0x99, + 0x01, 0x63, 0x8a, 0xa5, 0xbf, 0x68, 0x5c, 0xd3, + 0x3c, 0xbe, 0x0b, 0xd6, 0x76, 0x83, 0xd6, 0x57, + 0x05, 0x4a, 0x3d, 0xdd, 0x81, 0x73, 0xc9, 0xeb, + 0x8a, 0x84, 0x39, 0xf4, 0x36, 0x0b, 0xf7 +}; + +static const uint8_t g_ble_ll_dtm_prbs15_data[] = +{ + 0xff, 0x7f, 0xf0, 0x3e, 0x3a, 0x13, 0xa4, 0xdc, + 0xe2, 0xf9, 0x6c, 0x54, 0xe2, 0xd8, 0xea, 0xc8, + 0x88, 0x00, 0x21, 0x86, 0x9c, 0x6a, 0xd8, 0xcb, + 0x4e, 0x14, 0x6a, 0xf9, 0x4d, 0xd2, 0x7e, 0xb2, + 0x32, 0x03, 0xc6, 0x14, 0x4b, 0x7f, 0xd1, 0xb8, + 0xa6, 0x79, 0x7c, 0x17, 0xac, 0xed, 0x06, 0xad, + 0xaf, 0x0a, 0x94, 0x7a, 0xba, 0x03, 0xe7, 0x92, + 0xd7, 0x15, 0x09, 0x73, 0xe8, 0x6d, 0x16, 0xee, + 0xe1, 0x3f, 0x78, 0x1f, 0x9d, 0x09, 0x52, 0x6e, + 0xf1, 0x7c, 0x36, 0x2a, 0x71, 0x6c, 0x75, 0x64, + 0x44, 0x80, 0x10, 0x43, 0x4e, 0x35, 0xec, 0x65, + 0x27, 0x0a, 0xb5, 0xfc, 0x26, 0x69, 0x3f, 0x59, + 0x99, 0x01, 0x63, 0x8a, 0xa5, 0xbf, 0x68, 0x5c, + 0xd3, 0x3c, 0xbe, 0x0b, 0xd6, 0x76, 0x83, 0xd6, + 0x57, 0x05, 0x4a, 0x3d, 0xdd, 0x81, 0x73, 0xc9, + 0xeb, 0x8a, 0x84, 0x39, 0xf4, 0x36, 0x0b, 0xf7, + 0xf0, 0x1f, 0xbc, 0x8f, 0xce, 0x04, 0x29, 0xb7, + 0x78, 0x3e, 0x1b, 0x95, 0x38, 0xb6, 0x3a, 0x32, + 0x22, 0x40, 0x88, 0x21, 0xa7, 0x1a, 0xf6, 0xb2, + 0x13, 0x85, 0x5a, 0x7e, 0x93, 0xb4, 0x9f, 0xac, + 0xcc, 0x80, 0x31, 0xc5, 0xd2, 0x5f, 0x34, 0xae, + 0x69, 0x1e, 0xdf, 0x05, 0x6b, 0xbb, 0x41, 0xeb, + 0xab, 0x02, 0xa5, 0x9e, 0xee, 0xc0, 0xb9, 0xe4, + 0x75, 0x45, 0xc2, 0x1c, 0x7a, 0x9b, 0x85, 0x7b, + 0xf8, 0x0f, 0xde, 0x47, 0x67, 0x82, 0x94, 0x5b, + 0x3c, 0x9f, 0x8d, 0x4a, 0x1c, 0x5b, 0x1d, 0x19, + 0x11, 0x20, 0xc4, 0x90, 0x53, 0x0d, 0x7b, 0xd9, + 0x89, 0x42, 0x2d, 0xbf, 0x49, 0xda, 0x4f, 0x56, + 0x66, 0xc0, 0x98, 0x62, 0xe9, 0x2f, 0x1a, 0xd7, + 0x34, 0x8f, 0xef, 0x82, 0xb5, 0xdd, 0xa0, 0xf5, + 0x55, 0x81, 0x52, 0x4f, 0x77, 0xe0, 0x5c, 0xf2, + 0xba, 0x22, 0x61, 0x0e, 0xbd, 0xcd, 0xc2 +}; + +static const uint8_t channel_rf_to_index[] = { + 37, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 38, 11 ,12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 39 +}; + +#define BLE_DTM_SYNC_WORD (0x71764129) +#define BLE_DTM_CRC (0x555555) + +static void ble_ll_dtm_ctx_free(struct dtm_ctx * ctx); + +static void +ble_ll_dtm_set_next(struct dtm_ctx *ctx) +{ + struct ble_ll_sched_item *sch = &ctx->sch; + + ctx->pdu_start_ticks += ctx->itvl_ticks; + ctx->pdu_start_usecs += ctx->itvl_rem_usec; + if (ctx->pdu_start_usecs >= 31) { + ctx->pdu_start_ticks++; + ctx->pdu_start_usecs -= 31; + } + + sch->start_time = ctx->pdu_start_ticks; + sch->remainder = ctx->pdu_start_usecs; + + sch->start_time -= g_ble_ll_sched_offset_ticks; +} + +static void +ble_ll_dtm_ev_tx_resched_cb(struct ble_npl_event *evt) { + /* It is called in LL context */ + struct dtm_ctx *ctx = ble_npl_event_get_arg(evt); + int rc; + os_sr_t sr; + + OS_ENTER_CRITICAL(sr); + if (!ctx->active || !ctx->om) { + OS_EXIT_CRITICAL(sr); + return; + } + OS_EXIT_CRITICAL(sr); + +#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS) + if (g_ble_ll_dtm_ctx.num_of_packets_max && + (g_ble_ll_dtm_ctx.num_of_packets == g_ble_ll_dtm_ctx.num_of_packets_max)) { + /* + * XXX do not send more packets, but also do not stop DTM - it shall be + * stopped as usual by HCI command since there is no standard way to + * signal end of test to host. + */ + return; + } +#endif + + ble_ll_dtm_set_next(ctx); + rc = ble_ll_sched_dtm(&ctx->sch); + BLE_LL_ASSERT(rc == 0); +} + +static int ble_ll_dtm_rx_start(void); + +static void +ble_ll_dtm_ev_rx_restart_cb(struct ble_npl_event *evt) { + if (ble_ll_dtm_rx_start() != 0) { + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_dtm_ctx.evt); + STATS_INC(ble_ll_dtm_stats, rx_failed); + } +} + +static void +ble_ll_dtm_tx_done(void *arg) +{ + struct dtm_ctx *ctx; + + ctx = arg; + if (!ctx->active) { + return; + } + + g_ble_ll_dtm_ctx.num_of_packets++; + + /* Reschedule event in LL context */ + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &ctx->evt); + + ble_ll_state_set(BLE_LL_STATE_STANDBY); +} + +static int +ble_ll_dtm_tx_sched_cb(struct ble_ll_sched_item *sch) +{ + struct dtm_ctx *ctx = sch->cb_arg; + int rc; + + if (!ctx->active) { + return BLE_LL_SCHED_STATE_DONE; + } + + rc = ble_phy_setchan(channel_rf_to_index[ctx->rf_channel], + BLE_DTM_SYNC_WORD, BLE_DTM_CRC); + if (rc != 0) { + BLE_LL_ASSERT(0); + return BLE_LL_SCHED_STATE_DONE; + } + +#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)) + ble_phy_mode_set(ctx->phy_mode, ctx->phy_mode); +#endif + ble_phy_set_txend_cb(ble_ll_dtm_tx_done, ctx); + ble_phy_txpwr_set(0); + + sch->start_time += g_ble_ll_sched_offset_ticks; + + rc = ble_phy_tx_set_start_time(sch->start_time, sch->remainder); + if (rc) { + goto resched; + } + + rc = ble_phy_tx(ble_ll_tx_mbuf_pducb, ctx->om, BLE_PHY_TRANSITION_NONE); + if (rc) { + goto resched; + } + + ble_ll_state_set(BLE_LL_STATE_DTM); + + return BLE_LL_SCHED_STATE_DONE; + +resched: + /* Reschedule from LL task if late for this PDU */ + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &ctx->evt); + + STATS_INC(ble_ll_dtm_stats, tx_failed); + + return BLE_LL_SCHED_STATE_DONE; +} + +static void +ble_ll_dtm_calculate_itvl(struct dtm_ctx *ctx, uint8_t len, + uint16_t cmd_interval, int phy_mode) +{ + uint32_t l; + uint32_t itvl_usec; + uint32_t itvl_ticks; + + /* Calculate interval as per spec Bluetooth 5.0 Vol 6. Part F, 4.1.6 */ + l = ble_ll_pdu_tx_time_get(len + BLE_LL_PDU_HDR_LEN, phy_mode); + itvl_usec = ((l + 249 + 624) / 625) * 625; + +#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS) + if (cmd_interval > itvl_usec) { + itvl_usec = cmd_interval; + } +#endif + + itvl_ticks = os_cputime_usecs_to_ticks(itvl_usec); + ctx->itvl_rem_usec = (itvl_usec - os_cputime_ticks_to_usecs(itvl_ticks)); + if (ctx->itvl_rem_usec == 31) { + ctx->itvl_rem_usec = 0; + ++itvl_ticks; + } + ctx->itvl_ticks = itvl_ticks; +} + +static int +ble_ll_dtm_tx_create_ctx(uint8_t packet_payload, uint8_t len, + uint8_t rf_channel, uint8_t phy_mode, + uint16_t cmd_interval, uint16_t cmd_pkt_count) +{ + int rc = 0; + uint8_t byte_pattern; + struct ble_mbuf_hdr *ble_hdr; + struct os_mbuf *m; + struct dtm_ctx *ctx = &g_ble_ll_dtm_ctx; + struct ble_ll_sched_item *sch = &ctx->sch; + + /* MSYS is big enough to get continues memory */ + m = os_msys_get_pkthdr(len, sizeof(struct ble_mbuf_hdr)); + ctx->om = m; + BLE_LL_ASSERT(g_ble_ll_dtm_ctx.om); + + ctx->phy_mode = phy_mode; + ctx->rf_channel = rf_channel; + ctx->num_of_packets = 0; +#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS) + ctx->num_of_packets_max = cmd_pkt_count; +#endif + + /* Set BLE transmit header */ + ble_hdr = BLE_MBUF_HDR_PTR(m); + ble_hdr->txinfo.flags = 0; + ble_hdr->txinfo.offset = 0; + ble_hdr->txinfo.pyld_len = len; + ble_hdr->txinfo.hdr_byte = packet_payload; + + switch(packet_payload) { + case 0x00: + if (os_mbuf_copyinto(m, 0, &g_ble_ll_dtm_prbs9_data, len)) { + return 1; + } + goto schedule; + case 0x01: + byte_pattern = 0x0F; + break; + case 0x02: + byte_pattern = 0x55; + break; + case 0x03: + if (os_mbuf_copyinto(m, 0, &g_ble_ll_dtm_prbs15_data, len)) { + return 1; + } + goto schedule; + case 0x04: + byte_pattern = 0xFF; + break; + case 0x05: + byte_pattern = 0x00; + break; + case 0x06: + byte_pattern = 0xF0; + break; + case 0x07: + byte_pattern = 0xAA; + break; + default: + return 1; + } + + for (rc = 0; rc < len; rc++) { + if (os_mbuf_copyinto(m, rc, &byte_pattern, 1)) { + return 1; + } + } + +schedule: + ble_phy_enable_dtm(); + + sch->sched_cb = ble_ll_dtm_tx_sched_cb; + sch->cb_arg = ctx; + sch->sched_type = BLE_LL_SCHED_TYPE_DTM; + + /* Prepare os_event */ + ble_npl_event_init(&ctx->evt, ble_ll_dtm_ev_tx_resched_cb, ctx); + + ble_ll_dtm_calculate_itvl(ctx, len, cmd_interval, phy_mode); + + ctx->pdu_start_ticks = ble_ll_rfmgmt_enable_now(); + ctx->pdu_start_usecs = 0; + ble_ll_dtm_set_next(ctx); + + /* Set some start point for TX packets */ + rc = ble_ll_sched_dtm(sch); + BLE_LL_ASSERT(rc == 0); + + g_ble_ll_dtm_ctx.active = 1; + return 0; +} + +static int +ble_ll_dtm_rx_start(void) +{ + os_sr_t sr; + int rc; + + rc = ble_phy_setchan(channel_rf_to_index[g_ble_ll_dtm_ctx.rf_channel], + BLE_DTM_SYNC_WORD, BLE_DTM_CRC); + if (rc) { + return rc; + } + +#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)) + ble_phy_mode_set(g_ble_ll_dtm_ctx.phy_mode, g_ble_ll_dtm_ctx.phy_mode); +#endif + + OS_ENTER_CRITICAL(sr); + rc = ble_phy_rx_set_start_time(os_cputime_get32(), 0); + OS_EXIT_CRITICAL(sr); + if (rc && rc != BLE_PHY_ERR_RX_LATE) { + return rc; + } + + ble_ll_state_set(BLE_LL_STATE_DTM); + + return 0; +} + +static int +ble_ll_dtm_rx_sched_cb(struct ble_ll_sched_item *sch) +{ + if (ble_ll_dtm_rx_start() != 0) { + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_dtm_ctx.evt); + STATS_INC(ble_ll_dtm_stats, rx_failed); + } + + return BLE_LL_SCHED_STATE_DONE; +} + +static int +ble_ll_dtm_rx_create_ctx(uint8_t rf_channel, uint8_t phy_mode) +{ + struct ble_ll_sched_item *sch = &g_ble_ll_dtm_ctx.sch; + int rc; + + g_ble_ll_dtm_ctx.phy_mode = phy_mode; + g_ble_ll_dtm_ctx.rf_channel = rf_channel; + + STATS_CLEAR(ble_ll_dtm_stats, rx_count); + + ble_npl_event_init(&g_ble_ll_dtm_ctx.evt, ble_ll_dtm_ev_rx_restart_cb, + NULL); + + sch->sched_cb = ble_ll_dtm_rx_sched_cb; + sch->cb_arg = &g_ble_ll_dtm_ctx; + sch->sched_type = BLE_LL_SCHED_TYPE_DTM; + sch->start_time = ble_ll_rfmgmt_enable_now(); + + rc = ble_ll_sched_dtm(sch); + BLE_LL_ASSERT(rc == 0); + + ble_phy_enable_dtm(); + + g_ble_ll_dtm_ctx.active = 1; + return 0; +} + +static void +ble_ll_dtm_ctx_free(struct dtm_ctx * ctx) +{ + os_sr_t sr; + + OS_ENTER_CRITICAL(sr); + if (!ctx->active) { + OS_EXIT_CRITICAL(sr); + return; + } + + ble_ll_sched_rmv_elem(&ctx->sch); + ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &g_ble_ll_dtm_ctx.evt); + + ble_phy_disable(); + ble_phy_disable_dtm(); + ble_ll_state_set(BLE_LL_STATE_STANDBY); + ble_ll_rfmgmt_release(); + + os_mbuf_free_chain(ctx->om); + memset(ctx, 0, sizeof(*ctx)); + OS_EXIT_CRITICAL(sr); +} + +static int +ble_ll_dtm_tx_test(uint8_t tx_chan, uint8_t len, uint8_t packet_payload, + uint8_t hci_phy, uint16_t interval, uint16_t pkt_count) +{ + uint8_t phy_mode; + + if (g_ble_ll_dtm_ctx.active) { + return BLE_ERR_CTLR_BUSY; + } + + switch (hci_phy) { + case BLE_HCI_LE_PHY_1M: + phy_mode = BLE_PHY_MODE_1M; + break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) + case BLE_HCI_LE_PHY_2M: + phy_mode = BLE_PHY_MODE_2M; + break; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + case BLE_HCI_LE_PHY_CODED_S8: + phy_mode = BLE_PHY_MODE_CODED_125KBPS; + break; + case BLE_HCI_LE_PHY_CODED_S2: + phy_mode = BLE_PHY_MODE_CODED_500KBPS; + break; +#endif + default: + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (tx_chan > 0x27 || packet_payload > 0x07) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (ble_ll_dtm_tx_create_ctx(packet_payload, len, tx_chan, phy_mode, + interval, pkt_count)) { + return BLE_ERR_UNSPECIFIED; + } + + return BLE_ERR_SUCCESS; +} + +#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS) +static int +ble_ll_hci_dtm_tx_test_ext(const uint8_t *cmdbuf) +{ + const struct ble_hci_le_tx_test_ext_cp *cmd = (const void *) cmdbuf; + + return ble_ll_dtm_tx_test(cmd->tx_chan, cmd->test_data_len, cmd->payload, + BLE_HCI_LE_PHY_1M, le16toh(cmd->interval), + le16toh(cmd->pkt_count)); +} + +static int +ble_ll_hci_dtm_tx_test_v2_ext(const uint8_t *cmdbuf) +{ + const struct ble_hci_le_tx_test_v2_ext_cp *cmd = (const void *) cmdbuf; + + return ble_ll_dtm_tx_test(cmd->tx_chan, cmd->test_data_len, cmd->payload, + cmd->phy, le16toh(cmd->interval), + le16toh(cmd->pkt_count)); +} +#endif + +int +ble_ll_hci_dtm_tx_test(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_tx_test_cp *cmd = (const void *) cmdbuf; + +#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS) + if (len == sizeof(struct ble_hci_le_tx_test_ext_cp)) { + return ble_ll_hci_dtm_tx_test_ext(cmdbuf); + } +#endif + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + return ble_ll_dtm_tx_test(cmd->tx_chan, cmd->test_data_len, cmd->payload, + BLE_HCI_LE_PHY_1M, 0, 0); +} + +int +ble_ll_hci_dtm_tx_test_v2(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_tx_test_v2_cp *cmd = (const void *) cmdbuf; + +#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS) + if (len == sizeof(struct ble_hci_le_tx_test_v2_ext_cp)) { + return ble_ll_hci_dtm_tx_test_v2_ext(cmdbuf); + } +#endif + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + return ble_ll_dtm_tx_test(cmd->tx_chan, cmd->test_data_len, cmd->payload, + cmd->phy, 0, 0); +} + +static int +ble_ll_dtm_rx_test(uint8_t rx_chan, uint8_t hci_phy) +{ + uint8_t phy_mode; + + if (g_ble_ll_dtm_ctx.active) { + return BLE_ERR_CTLR_BUSY; + } + + switch (hci_phy) { + case BLE_HCI_LE_PHY_1M: + phy_mode = BLE_PHY_MODE_1M; + break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) + case BLE_HCI_LE_PHY_2M: + phy_mode = BLE_PHY_MODE_2M; + break; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + case BLE_HCI_LE_PHY_CODED: + phy_mode = BLE_PHY_MODE_CODED_500KBPS; + break; +#endif + default: + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (rx_chan > 0x27) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (ble_ll_dtm_rx_create_ctx(rx_chan, phy_mode)) { + return BLE_ERR_UNSPECIFIED; + } + + return BLE_ERR_SUCCESS; +} + +int ble_ll_hci_dtm_rx_test(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_rx_test_cp *cmd = (const void *) cmdbuf; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + return ble_ll_dtm_rx_test(cmd->rx_chan, BLE_HCI_LE_PHY_1M); +} + +int ble_ll_hci_dtm_rx_test_v2(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_rx_test_v2_cp *cmd = (const void *) cmdbuf; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* TODO ignoring modulation index */ + + return ble_ll_dtm_rx_test(cmd->rx_chan, cmd->phy); +} + +int ble_ll_dtm_end_test(uint8_t *rsp, uint8_t *rsplen) +{ + put_le16(rsp, g_ble_ll_dtm_ctx. num_of_packets); + *rsplen = 2; + + ble_ll_dtm_ctx_free(&g_ble_ll_dtm_ctx); + return BLE_ERR_SUCCESS; +} + +int ble_ll_dtm_rx_isr_start(struct ble_mbuf_hdr *rxhdr, uint32_t aa) +{ + return 0; +} + +void +ble_ll_dtm_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr) +{ + if (BLE_MBUF_HDR_CRC_OK(hdr)) { + /* XXX Compare data. */ + g_ble_ll_dtm_ctx.num_of_packets++; + STATS_INC(ble_ll_dtm_stats, rx_count); + } + + if (ble_ll_dtm_rx_start() != 0) { + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_dtm_ctx.evt); + STATS_INC(ble_ll_dtm_stats, rx_failed); + } +} + +int +ble_ll_dtm_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) +{ + struct os_mbuf *rxpdu; + + if (!g_ble_ll_dtm_ctx.active) { + return -1; + } + + rxpdu = ble_ll_rxpdu_alloc(rxbuf[1] + BLE_LL_PDU_HDR_LEN); + + /* Copy the received pdu and hand it up */ + if (rxpdu) { + ble_phy_rxpdu_copy(rxbuf, rxpdu); + ble_ll_rx_pdu_in(rxpdu); + } + + return 0; +} + +void +ble_ll_dtm_wfr_timer_exp(void) +{ + /* Should not be needed */ + BLE_LL_ASSERT(0); +} + + +void +ble_ll_dtm_reset(void) +{ + ble_ll_dtm_ctx_free(&g_ble_ll_dtm_ctx); +} + +void +ble_ll_dtm_init(void) +{ + int rc; + + rc = stats_init_and_reg(STATS_HDR(ble_ll_dtm_stats), + STATS_SIZE_INIT_PARMS(ble_ll_dtm_stats, STATS_SIZE_32), + STATS_NAME_INIT_PARMS(ble_ll_dtm_stats), + "ble_ll_dtm"); + SYSINIT_PANIC_ASSERT(rc == 0); +} +#endif +#endif \ No newline at end of file diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_dtm_priv.h similarity index 53% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_dtm_priv.h index 9f7d8d16b..e04af07be 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_dtm_priv.h @@ -17,25 +17,24 @@ * under the License. */ -#ifndef H_BLE_HS_ATOMIC_ -#define H_BLE_HS_ATOMIC_ +#ifndef H_BLE_LL_TEST_PRIV_ +#define H_BLE_LL_TEST_PRIV_ -#include "ble_hs_conn_priv.h" - -#ifdef __cplusplus -extern "C" { -#endif - -int ble_hs_atomic_conn_delete(uint16_t conn_handle); -void ble_hs_atomic_conn_insert(struct ble_hs_conn *conn); -int ble_hs_atomic_conn_flags(uint16_t conn_handle, - ble_hs_conn_flags_t *out_flags); -int ble_hs_atomic_conn_set_flags(uint16_t conn_handle, - ble_hs_conn_flags_t flags, int on); -uint16_t ble_hs_atomic_first_conn_handle(void); - -#ifdef __cplusplus -} -#endif +#include +#include +#include "nimble/ble.h" +int ble_ll_hci_dtm_tx_test(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_hci_dtm_tx_test_v2(const uint8_t *cmdbuf, uint8_t len); + +int ble_ll_hci_dtm_rx_test(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_hci_dtm_rx_test_v2(const uint8_t *cmdbuf, uint8_t len); + +int ble_ll_dtm_end_test(uint8_t *rsp, uint8_t *rsplen); + +int ble_ll_dtm_rx_isr_start(struct ble_mbuf_hdr *rxhdr, uint32_t aa); +int ble_ll_dtm_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr); +void ble_ll_dtm_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr); +void ble_ll_dtm_wfr_timer_exp(void); +void ble_ll_dtm_reset(void); #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_hci.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_hci.c new file mode 100644 index 000000000..d83af2c01 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_hci.c @@ -0,0 +1,1519 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef ESP_PLATFORM + +#include +#include +#include +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/include/nimble/nimble_opt.h" +#include "nimble/nimble/include/nimble/hci_common.h" +#include "nimble/nimble/include/nimble/ble_hci_trans.h" +#include "../include/controller/ble_hw.h" +#include "../include/controller/ble_ll_adv.h" +#include "../include/controller/ble_ll_scan.h" +#include "../include/controller/ble_ll.h" +#include "../include/controller/ble_ll_hci.h" +#include "../include/controller/ble_ll_whitelist.h" +#include "../include/controller/ble_ll_resolv.h" +#include "../include/controller/ble_ll_sync.h" +#include "ble_ll_priv.h" +#include "ble_ll_conn_priv.h" + +#if MYNEWT_VAL(BLE_LL_DTM) +#include "ble_ll_dtm_priv.h" +#endif + +static void ble_ll_hci_cmd_proc(struct ble_npl_event *ev); + +/* OS event to enqueue command */ +static struct ble_npl_event g_ble_ll_hci_cmd_ev; + +/* LE event mask */ +static uint64_t g_ble_ll_hci_le_event_mask; +static uint64_t g_ble_ll_hci_event_mask; +static uint64_t g_ble_ll_hci_event_mask2; + +static int16_t rx_path_pwr_compensation; +static int16_t tx_path_pwr_compensation; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +static enum { + ADV_MODE_ANY, + ADV_MODE_LEGACY, + ADV_MODE_EXT, +} hci_adv_mode; + +bool ble_ll_hci_adv_mode_ext(void) +{ + return hci_adv_mode == ADV_MODE_EXT; +} +#else +bool +ble_ll_hci_adv_mode_ext(void) +{ + return false; +} +#endif + +/** + * ll hci get num cmd pkts + * + * Returns the number of command packets that the host is allowed to send + * to the controller. + * + * @return uint8_t + */ +static uint8_t +ble_ll_hci_get_num_cmd_pkts(void) +{ + return BLE_LL_CFG_NUM_HCI_CMD_PKTS; +} + +/** + * Send an event to the host. + * + * @param evbuf Pointer to event buffer to send + * + * @return int 0: success; -1 otherwise. + */ +int +ble_ll_hci_event_send(struct ble_hci_ev *hci_ev) +{ + int rc; + + BLE_LL_DEBUG_GPIO(HCI_EV, 1); + + BLE_LL_ASSERT(sizeof(*hci_ev) + hci_ev->length <= BLE_LL_MAX_EVT_LEN); + + /* Count number of events sent */ + STATS_INC(ble_ll_stats, hci_events_sent); + + /* Send the event to the host */ + rc = ble_hci_trans_ll_evt_tx((uint8_t *)hci_ev); + + BLE_LL_DEBUG_GPIO(HCI_EV, 0); + + return rc; +} + +/** + * Created and sends a command complete event with the no-op opcode to the + * host. + */ +void +ble_ll_hci_send_noop(void) +{ + struct ble_hci_ev_command_complete_nop *ev; + struct ble_hci_ev *hci_ev; + + hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (hci_ev) { + /* Create a command complete event with a NO-OP opcode */ + hci_ev->opcode = BLE_HCI_EVCODE_COMMAND_COMPLETE; + + hci_ev->length = sizeof(*ev); + ev = (void *)hci_ev->data; + + ev->num_packets = ble_ll_hci_get_num_cmd_pkts(); + ev->opcode = BLE_HCI_OPCODE_NOP; + + ble_ll_hci_event_send(hci_ev); + } +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) +/** + * LE encrypt command + * + * @param cmdbuf + * @param rspbuf + * @param rsplen + * + * @return int + */ +static int +ble_ll_hci_le_encrypt(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, + uint8_t *rsplen) +{ + const struct ble_hci_le_encrypt_cp *cmd = (const void *) cmdbuf; + struct ble_hci_le_encrypt_rp *rsp = (void *)rspbuf; + struct ble_encryption_block ecb; + int rc; + + /* Call the link layer to encrypt the data */ + swap_buf(ecb.key, cmd->key, BLE_ENC_BLOCK_SIZE); + swap_buf(ecb.plain_text, cmd->data, BLE_ENC_BLOCK_SIZE); + rc = ble_hw_encrypt_block(&ecb); + if (!rc) { + swap_buf(rsp->data, ecb.cipher_text, BLE_ENC_BLOCK_SIZE); + *rsplen = sizeof(*rsp); + rc = BLE_ERR_SUCCESS; + } else { + rc = BLE_ERR_CTLR_BUSY; + } + + return rc; +} +#endif + +/** + * LE rand command + * + * @param cmdbuf + * @param rspbuf + * @param rsplen + * + * @return int + */ +static int +ble_ll_hci_le_rand(uint8_t *rspbuf, uint8_t *rsplen) +{ + struct ble_hci_le_rand_rp *rsp = (void *) rspbuf; + + ble_ll_rand_data_get((uint8_t *)&rsp->random_number, + sizeof(rsp->random_number)); + + *rsplen = sizeof(*rsp); + return BLE_ERR_SUCCESS; +} + +/** + * Read local version + * + * @param rspbuf + * @param rsplen + * + * @return int + */ +static int +ble_ll_hci_rd_local_version(uint8_t *rspbuf, uint8_t *rsplen) +{ + struct ble_hci_ip_rd_local_ver_rp *rsp = (void *) rspbuf; + + rsp->hci_ver = BLE_HCI_VER_BCS; + rsp->hci_rev = 0; + rsp->lmp_ver = BLE_LMP_VER_BCS; + rsp->manufacturer = htole16(MYNEWT_VAL(BLE_LL_MFRG_ID)); + rsp->lmp_subver = 0; + + *rsplen = sizeof(*rsp); + return BLE_ERR_SUCCESS; +} + +/** + * Read local supported features + * + * @param rspbuf + * @param rsplen + * + * @return int + */ +static int +ble_ll_hci_rd_local_supp_feat(uint8_t *rspbuf, uint8_t *rsplen) +{ + struct ble_hci_ip_rd_loc_supp_feat_rp *rsp = (void *) rspbuf; + + /* + * The only two bits we set here currently are (5th byte): + * BR/EDR not supported (bit 5) + * LE supported (controller) (bit 6) + */ + rsp->features = htole64(0x0000006000000000); + + *rsplen = sizeof(*rsp); + return BLE_ERR_SUCCESS; +} + +/** + * Read local supported commands + * + * @param rspbuf + * @param rsplen + * + * @return int + */ +static int +ble_ll_hci_rd_local_supp_cmd(uint8_t *rspbuf, uint8_t *rsplen) +{ + struct ble_hci_ip_rd_loc_supp_cmd_rp *rsp = (void *) rspbuf; + + memset(rsp->commands, 0, sizeof(rsp->commands)); + memcpy(rsp->commands, g_ble_ll_supp_cmds, sizeof(g_ble_ll_supp_cmds)); + + *rsplen = sizeof(*rsp); + return BLE_ERR_SUCCESS; +} + +/** + * Called to read the public device address of the device + * + * + * @param rspbuf + * @param rsplen + * + * @return int + */ +static int +ble_ll_hci_rd_bd_addr(uint8_t *rspbuf, uint8_t *rsplen) +{ + struct ble_hci_ip_rd_bd_addr_rp *rsp = (void *) rspbuf; + + memcpy(rsp->addr, g_dev_addr, BLE_DEV_ADDR_LEN); + + *rsplen = sizeof(*rsp); + return BLE_ERR_SUCCESS; +} + +/** + * ll hci set le event mask + * + * Called when the LL controller receives a set LE event mask command. + * + * Context: Link Layer task (HCI command parser) + * + * @param cmdbuf Pointer to command buf. + * + * @return int BLE_ERR_SUCCESS. Does not return any errors. + */ +static int +ble_ll_hci_set_le_event_mask(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_set_event_mask_cp *cmd = (const void *) cmdbuf; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + g_ble_ll_hci_le_event_mask = le64toh(cmd->event_mask); + + return BLE_ERR_SUCCESS; +} + +/** + * HCI read buffer size command. Returns the ACL data packet length and + * num data packets. + * + * @param rspbuf Pointer to response buffer + * @param rsplen Length of response buffer + * + * @return int BLE error code + */ +static int +ble_ll_hci_le_read_bufsize(uint8_t *rspbuf, uint8_t *rsplen) +{ + struct ble_hci_le_rd_buf_size_rp *rp = (void *) rspbuf; + + rp->data_len = htole16(g_ble_ll_data.ll_acl_pkt_size); + rp->data_packets = g_ble_ll_data.ll_num_acl_pkts; + + *rsplen = sizeof(*rp); + return BLE_ERR_SUCCESS; +} + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +/** + * Checks the preferred phy masks for validity and places the preferred masks + * in the input phy masks + + * @return int BLE_ERR_SUCCESS or BLE_ERR_INV_HCI_CMD_PARMS or BLE_ERR_UNSUPPORTED + */ +int +ble_ll_hci_chk_phy_masks(uint8_t all_phys, uint8_t tx_phys, uint8_t rx_phys, + uint8_t *txphy, uint8_t *rxphy) +{ + /* Check for RFU */ + if ((tx_phys & ~BLE_HCI_LE_PHY_PREF_MASK_ALL) || + (rx_phys & ~BLE_HCI_LE_PHY_PREF_MASK_ALL)) { + return BLE_ERR_UNSUPPORTED; + } + + if ((!(all_phys & BLE_HCI_LE_PHY_NO_TX_PREF_MASK) && (tx_phys == 0)) || + (!(all_phys & BLE_HCI_LE_PHY_NO_RX_PREF_MASK) && (rx_phys == 0))) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* If phy not supported, return error */ +#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) + if((tx_phys & BLE_HCI_LE_PHY_2M_PREF_MASK) || + (rx_phys & BLE_HCI_LE_PHY_2M_PREF_MASK)) { + return BLE_ERR_UNSUPPORTED; + } +#endif +#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + if ((tx_phys & BLE_HCI_LE_PHY_CODED_PREF_MASK) || + (rx_phys & BLE_HCI_LE_PHY_CODED_PREF_MASK)) { + return BLE_ERR_UNSUPPORTED; + } +#endif + /* Set the default PHY preferences */ + if (all_phys & BLE_HCI_LE_PHY_NO_TX_PREF_MASK) { + tx_phys = BLE_HCI_LE_PHY_PREF_MASK_ALL; + } + *txphy = tx_phys; + + if (all_phys & BLE_HCI_LE_PHY_NO_RX_PREF_MASK) { + rx_phys = BLE_HCI_LE_PHY_PREF_MASK_ALL; + } + *rxphy = rx_phys; + + return BLE_ERR_SUCCESS; +} + +/** + * Set PHY preferences for connection + * + * @param cmdbuf + * + * @return int + */ +static int +ble_ll_hci_le_set_def_phy(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_set_default_phy_cp *cmd = (const void *) cmdbuf; + int rc; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + rc = ble_ll_hci_chk_phy_masks(cmd->all_phys, cmd->tx_phys, cmd->rx_phys, + &g_ble_ll_data.ll_pref_tx_phys, + &g_ble_ll_data.ll_pref_rx_phys); + return rc; +} +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) +/** + * HCI write suggested default data length command. + * + * This command is used by the host to change the initial max tx octets/time + * for all connections. Note that if the controller does not support the + * requested times no error is returned; the controller simply ignores the + * request (but remembers what the host requested for the read suggested + * default data length command). The spec allows for the controller to + * disregard the host. + * + * @param rspbuf Pointer to response buffer + * @param rsplen Length of response buffer + * + * @return int BLE error code + */ +static int +ble_ll_hci_le_wr_sugg_data_len(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_wr_sugg_def_data_len_cp *cmd = (const void*) cmdbuf; + uint16_t tx_oct; + uint16_t tx_time; + int rc; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Get suggested octets and time */ + tx_oct = le16toh(cmd->max_tx_octets); + tx_time = le16toh(cmd->max_tx_time); + + /* If valid, write into suggested and change connection initial times */ + if (ble_ll_chk_txrx_octets(tx_oct) && ble_ll_chk_txrx_time(tx_time)) { + g_ble_ll_conn_params.sugg_tx_octets = (uint8_t)tx_oct; + g_ble_ll_conn_params.sugg_tx_time = tx_time; + + /* + * We can disregard host suggestion, but we are a nice controller so + * let's use host suggestion, unless they exceed max supported values + * in which case we just use our max. + */ + g_ble_ll_conn_params.conn_init_max_tx_octets = + min(tx_oct, g_ble_ll_conn_params.supp_max_tx_octets); + g_ble_ll_conn_params.conn_init_max_tx_time = + min(tx_time, g_ble_ll_conn_params.supp_max_tx_time); + + /* + * Use the same for coded and uncoded defaults. These are used when PHY + * parameters are initialized and we want to use values overridden by + * host. Make sure we do not exceed max supported time on uncoded. + */ + g_ble_ll_conn_params.conn_init_max_tx_time_uncoded = + min(BLE_LL_CONN_SUPP_TIME_MAX_UNCODED, + g_ble_ll_conn_params.conn_init_max_tx_time); + g_ble_ll_conn_params.conn_init_max_tx_time_coded = + g_ble_ll_conn_params.conn_init_max_tx_time; + + rc = BLE_ERR_SUCCESS; + } else { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + } + + return rc; +} + +/** + * HCI read suggested default data length command. Returns the controllers + * initial max tx octet/time. + * + * @param rspbuf Pointer to response buffer + * @param rsplen Length of response buffer + * + * @return int BLE error code + */ +static int +ble_ll_hci_le_rd_sugg_data_len(uint8_t *rspbuf, uint8_t *rsplen) +{ + struct ble_hci_le_rd_sugg_def_data_len_rp *rsp = (void *) rspbuf; + + /* Place the data packet length and number of packets in the buffer */ + rsp->max_tx_octets = htole16(g_ble_ll_conn_params.sugg_tx_octets); + rsp->max_tx_time = htole16(g_ble_ll_conn_params.sugg_tx_time); + + *rsplen = sizeof(*rsp); + return BLE_ERR_SUCCESS; +} + +/** + * HCI read maximum data length command. Returns the controllers max supported + * rx/tx octets/times. + * + * @param rspbuf Pointer to response buffer + * @param rsplen Length of response buffer + * + * @return int BLE error code + */ +static int +ble_ll_hci_le_rd_max_data_len(uint8_t *rspbuf, uint8_t *rsplen) +{ + struct ble_hci_le_rd_max_data_len_rp *rsp = (void *)rspbuf; + + /* Place the data packet length and number of packets in the buffer */ + rsp->max_tx_octests = htole16(g_ble_ll_conn_params.supp_max_tx_octets); + rsp->max_tx_time = htole16(g_ble_ll_conn_params.supp_max_tx_time); + rsp->max_rx_octests = htole16(g_ble_ll_conn_params.supp_max_rx_octets); + rsp->max_rx_time = htole16(g_ble_ll_conn_params.supp_max_rx_time); + + *rsplen = sizeof(*rsp); + return BLE_ERR_SUCCESS; +} +#endif + +/** + * HCI read local supported features command. Returns the features + * supported by the controller. + * + * @param rspbuf Pointer to response buffer + * @param rsplen Length of response buffer + * + * @return int BLE error code + */ +static int +ble_ll_hci_le_read_local_features(uint8_t *rspbuf, uint8_t *rsplen) +{ + struct ble_hci_le_rd_loc_supp_feat_rp *rsp = (void *) rspbuf; + + rsp->features = htole64(ble_ll_read_supp_features()); + + *rsplen = sizeof(*rsp); + return BLE_ERR_SUCCESS; +} + +/** + * HCI read local supported states command. Returns the states + * supported by the controller. + * + * @param rspbuf Pointer to response buffer + * @param rsplen Length of response buffer + * + * @return int BLE error code + */ +static int +ble_ll_hci_le_read_supp_states(uint8_t *rspbuf, uint8_t *rsplen) +{ + struct ble_hci_le_rd_supp_states_rp *rsp = (void *) rspbuf; + + /* Add list of supported states. */ + rsp->states = htole64(ble_ll_read_supp_states()); + + *rsplen = sizeof(*rsp); + return BLE_ERR_SUCCESS; +} + + +/** + * Checks to see if a LE event has been disabled by the host. + * + * @param subev Sub-event code of the LE Meta event. Note that this can + * be a value from 1 to 64, inclusive. + * + * @return uint8_t 0: event is not enabled; otherwise event is enabled. + */ +bool +ble_ll_hci_is_le_event_enabled(unsigned int subev) +{ + /* The LE meta event must be enabled for any LE event to be enabled */ + if (g_ble_ll_hci_event_mask & (1ull << (BLE_HCI_EVCODE_LE_META - 1))) { + return g_ble_ll_hci_le_event_mask & (1ull << (subev - 1)); + } + + return false; +} + +/** + * Checks to see if an event has been disabled by the host. + * + * NOTE: there are two "pages" of event masks; the first page is for event + * codes between 0 and 63 and the second page is for event codes 64 and + * greater. + * + * @param evcode This is the event code for the event. + * + * @return uint8_t 0: event is not enabled; otherwise event is enabled. + */ +bool +ble_ll_hci_is_event_enabled(unsigned int evcode) +{ + if (evcode >= 64) { + return g_ble_ll_hci_event_mask2 & (1ull << (evcode - 64)); + } + + return g_ble_ll_hci_event_mask & (1ull << (evcode - 1)); +} + +/** + * Called to determine if the reply to the command should be a command complete + * event or a command status event. + * + * @param ocf + * + * @return int 0: return command complete; 1: return command status event + */ +static int +ble_ll_hci_le_cmd_send_cmd_status(uint16_t ocf) +{ + int rc; + + switch (ocf) { + case BLE_HCI_OCF_LE_RD_REM_FEAT: + case BLE_HCI_OCF_LE_CREATE_CONN: + case BLE_HCI_OCF_LE_EXT_CREATE_CONN: + case BLE_HCI_OCF_LE_CONN_UPDATE: + case BLE_HCI_OCF_LE_START_ENCRYPT: + case BLE_HCI_OCF_LE_RD_P256_PUBKEY: + case BLE_HCI_OCF_LE_GEN_DHKEY: + case BLE_HCI_OCF_LE_SET_PHY: + case BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC: + rc = 1; + break; + default: + rc = 0; + break; + } + return rc; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +/** HCI LE read maximum advertising data length command. Returns the controllers +* max supported advertising data length; +* +* @param rspbuf Pointer to response buffer +* @param rsplen Length of response buffer +* +* @return int BLE error code +*/ +static int +ble_ll_adv_rd_max_adv_data_len(uint8_t *rspbuf, uint8_t *rsplen) +{ + struct ble_hci_le_rd_max_adv_data_len_rp *rsp = (void *) rspbuf; + + rsp->max_adv_data_len = htole16(BLE_ADV_DATA_MAX_LEN); + + *rsplen = sizeof(*rsp); + return BLE_ERR_SUCCESS; +} + +/** + * HCI LE read number of supported advertising sets + * + * @param rspbuf Pointer to response buffer + * @param rsplen Length of response buffer + * + * @return int BLE error code + */ +static int +ble_ll_adv_rd_sup_adv_sets(uint8_t *rspbuf, uint8_t *rsplen) +{ + struct ble_hci_le_rd_num_of_adv_sets_rp *rsp = (void *)rspbuf; + + rsp->num_sets = BLE_ADV_INSTANCES; + + *rsplen = sizeof(*rsp); + return BLE_ERR_SUCCESS; +} + +static bool +ble_ll_is_valid_adv_mode(uint8_t ocf) +{ + /* + * If, since the last power-on or reset, the Host has ever issued a legacy + * advertising command and then issues an extended advertising command, or + * has ever issued an extended advertising command and then issues a legacy + * advertising command, the Controller shall return the error code Command + * Disallowed (0x0C). + */ + + switch(ocf) { + case BLE_HCI_OCF_LE_CREATE_CONN: + case BLE_HCI_OCF_LE_SET_ADV_PARAMS: + case BLE_HCI_OCF_LE_SET_ADV_ENABLE: + case BLE_HCI_OCF_LE_SET_ADV_DATA: + case BLE_HCI_OCF_LE_SET_SCAN_PARAMS: + case BLE_HCI_OCF_LE_SET_SCAN_ENABLE: + case BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA: + case BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR: + if (hci_adv_mode == ADV_MODE_EXT) { + return false; + } + + hci_adv_mode = ADV_MODE_LEGACY; + break; + case BLE_HCI_OCF_LE_EXT_CREATE_CONN: + case BLE_HCI_OCF_LE_SET_EXT_ADV_DATA: + case BLE_HCI_OCF_LE_SET_EXT_ADV_ENABLE: + case BLE_HCI_OCF_LE_SET_EXT_ADV_PARAM: + case BLE_HCI_OCF_LE_SET_EXT_SCAN_ENABLE: + case BLE_HCI_OCF_LE_SET_EXT_SCAN_PARAM: + case BLE_HCI_OCF_LE_SET_EXT_SCAN_RSP_DATA: + case BLE_HCI_OCF_LE_RD_MAX_ADV_DATA_LEN: + case BLE_HCI_OCF_LE_RD_NUM_OF_ADV_SETS: + case BLE_HCI_OCF_LE_REMOVE_ADV_SET: + case BLE_HCI_OCF_LE_CLEAR_ADV_SETS: + case BLE_HCI_OCF_LE_SET_PERIODIC_ADV_PARAMS: + case BLE_HCI_OCF_LE_SET_PERIODIC_ADV_DATA: + case BLE_HCI_OCF_LE_SET_PERIODIC_ADV_ENABLE: + case BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC: + case BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC_CANCEL: + case BLE_HCI_OCF_LE_PERIODIC_ADV_TERM_SYNC: + case BLE_HCI_OCF_LE_ADD_DEV_TO_PERIODIC_ADV_LIST: + case BLE_HCI_OCF_LE_REM_DEV_FROM_PERIODIC_ADV_LIST: + case BLE_HCI_OCF_LE_CLEAR_PERIODIC_ADV_LIST: + case BLE_HCI_OCF_LE_RD_PERIODIC_ADV_LIST_SIZE: +#if MYNEWT_VAL(BLE_VERSION) >= 51 + case BLE_HCI_OCF_LE_PERIODIC_ADV_RECEIVE_ENABLE: +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) + case BLE_HCI_OCF_LE_PERIODIC_ADV_SYNC_TRANSFER: + case BLE_HCI_OCF_LE_PERIODIC_ADV_SET_INFO_TRANSFER: + case BLE_HCI_OCF_LE_PERIODIC_ADV_SYNC_TRANSFER_PARAMS: + case BLE_HCI_OCF_LE_SET_DEFAULT_SYNC_TRANSFER_PARAMS: +#endif + if (hci_adv_mode == ADV_MODE_LEGACY) { + return false; + } + + hci_adv_mode = ADV_MODE_EXT; + break; + default: + break; + } + + return true; +} +#endif + +static int +ble_ll_read_tx_power(uint8_t *rspbuf, uint8_t *rsplen) +{ + struct ble_hci_le_rd_transmit_power_rp *rsp = (void *) rspbuf; + + rsp->min_tx_power = ble_phy_txpower_round(-127); + rsp->max_tx_power = ble_phy_txpower_round(126); + + *rsplen = sizeof(*rsp); + return BLE_ERR_SUCCESS; +} + +static int +ble_ll_read_rf_path_compensation(uint8_t *rspbuf, uint8_t *rsplen) +{ + struct ble_hci_le_rd_rf_path_compensation_rp *rsp = (void *) rspbuf; + + rsp->rx_path_compensation = htole16(rx_path_pwr_compensation); + rsp->tx_path_compensation = htole16(tx_path_pwr_compensation); + + *rsplen = sizeof(*rsp);; + return BLE_ERR_SUCCESS; +} + +static int +ble_ll_write_rf_path_compensation(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_wr_rf_path_compensation_cp *cmd = (const void *)cmdbuf; + int16_t rx; + int16_t tx; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + tx = le16toh(cmd->tx_path_compensation); + rx = le16toh(cmd->rx_path_compensation); + + if ((tx < -1280) || (tx > 1280) || (rx < -1280) || (rx > 1280)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + tx_path_pwr_compensation = tx; + rx_path_pwr_compensation = rx; + + ble_phy_set_rx_pwr_compensation(rx_path_pwr_compensation / 10); + + return BLE_ERR_SUCCESS; +} + +int8_t +ble_ll_get_tx_pwr_compensation(void) +{ + return tx_path_pwr_compensation / 10; +} + +/** + * Process a LE command sent from the host to the controller. The HCI command + * has a 3 byte command header followed by data. The header is: + * -> opcode (2 bytes) + * -> Length of parameters (1 byte; does include command header bytes). + * + * @param cmdbuf Pointer to command buffer. Points to start of command header. + * @param ocf Opcode command field. + * @param *rsplen Pointer to length of response + * + * @return int This function returns a BLE error code. If a command status + * event should be returned as opposed to command complete, + * 256 gets added to the return value. + */ +static int +ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, + uint8_t *rspbuf, uint8_t *rsplen, + ble_ll_hci_post_cmd_complete_cb *cb) +{ + int rc; + + /* Assume error; if all pass rc gets set to 0 */ + rc = BLE_ERR_INV_HCI_CMD_PARMS; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (!ble_ll_is_valid_adv_mode(ocf)) { + rc = BLE_ERR_CMD_DISALLOWED; + + /* + * This code is here because we add 256 to the return code to denote + * that the reply to this command should be command status (as opposed to + * command complete). + * + * For unknown HCI command let us return always command status as per + * specification Bluetooth 5, Vol. 2, Chapter 4.4 + */ + if (ble_ll_hci_le_cmd_send_cmd_status(ocf)) { + rc += (BLE_ERR_MAX + 1); + } + + return rc; + } +#endif + + switch (ocf) { + case BLE_HCI_OCF_LE_SET_EVENT_MASK: + rc = ble_ll_hci_set_le_event_mask(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_RD_BUF_SIZE: + if (len == 0) { + rc = ble_ll_hci_le_read_bufsize(rspbuf, rsplen); + } + break; + case BLE_HCI_OCF_LE_RD_LOC_SUPP_FEAT: + if (len == 0) { + rc = ble_ll_hci_le_read_local_features(rspbuf, rsplen); + } + break; + case BLE_HCI_OCF_LE_SET_RAND_ADDR: +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + rc = ble_ll_set_random_addr(cmdbuf, len, hci_adv_mode == ADV_MODE_EXT); +#else + rc = ble_ll_set_random_addr(cmdbuf, len, false); +#endif + break; + case BLE_HCI_OCF_LE_SET_ADV_PARAMS: + rc = ble_ll_adv_set_adv_params(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR: + if (len == 0) { + rc = ble_ll_adv_read_txpwr(rspbuf, rsplen); + } + break; + case BLE_HCI_OCF_LE_SET_ADV_DATA: + rc = ble_ll_hci_set_adv_data(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA: + rc = ble_ll_hci_set_scan_rsp_data(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_SET_ADV_ENABLE: + rc = ble_ll_hci_adv_set_enable(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_SET_SCAN_PARAMS: + rc = ble_ll_scan_set_scan_params(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_SET_SCAN_ENABLE: + rc = ble_ll_hci_scan_set_enable(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_CREATE_CONN: + rc = ble_ll_conn_create(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_CREATE_CONN_CANCEL: + if (len == 0) { + rc = ble_ll_conn_create_cancel(cb); + } + break; + case BLE_HCI_OCF_LE_RD_WHITE_LIST_SIZE: + if (len == 0) { + rc = ble_ll_whitelist_read_size(rspbuf, rsplen); + } + break; + case BLE_HCI_OCF_LE_CLEAR_WHITE_LIST: + if (len == 0) { + rc = ble_ll_whitelist_clear(); + } + break; + case BLE_HCI_OCF_LE_ADD_WHITE_LIST: + rc = ble_ll_whitelist_add(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_RMV_WHITE_LIST: + rc = ble_ll_whitelist_rmv(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_CONN_UPDATE: + rc = ble_ll_conn_hci_update(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_SET_HOST_CHAN_CLASS: + rc = ble_ll_conn_hci_set_chan_class(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_RD_CHAN_MAP: + rc = ble_ll_conn_hci_rd_chan_map(cmdbuf, len, rspbuf, rsplen); + break; + case BLE_HCI_OCF_LE_RD_REM_FEAT: + rc = ble_ll_conn_hci_read_rem_features(cmdbuf, len); + break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + case BLE_HCI_OCF_LE_ENCRYPT: + rc = ble_ll_hci_le_encrypt(cmdbuf, len, rspbuf, rsplen); + break; +#endif + case BLE_HCI_OCF_LE_RAND: + if (len == 0) { + rc = ble_ll_hci_le_rand(rspbuf, rsplen); + } + break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + case BLE_HCI_OCF_LE_START_ENCRYPT: + rc = ble_ll_conn_hci_le_start_encrypt(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_LT_KEY_REQ_REPLY: + rc = ble_ll_conn_hci_le_ltk_reply(cmdbuf, len, rspbuf, rsplen); + break; + case BLE_HCI_OCF_LE_LT_KEY_REQ_NEG_REPLY: + rc = ble_ll_conn_hci_le_ltk_neg_reply(cmdbuf, len, rspbuf, rsplen); + break; +#endif + case BLE_HCI_OCF_LE_RD_SUPP_STATES : + if (len == 0) { + rc = ble_ll_hci_le_read_supp_states(rspbuf, rsplen); + } + break; +#if MYNEWT_VAL(BLE_LL_DTM) + case BLE_HCI_OCF_LE_TX_TEST: + rc = ble_ll_hci_dtm_tx_test(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_RX_TEST: + rc = ble_ll_hci_dtm_rx_test(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_TEST_END: + if (len == 0) { + rc = ble_ll_dtm_end_test(rspbuf, rsplen); + } + break; +#endif + case BLE_HCI_OCF_LE_REM_CONN_PARAM_RR: + rc = ble_ll_conn_hci_param_rr(cmdbuf, len, rspbuf, rsplen); + break; + case BLE_HCI_OCF_LE_REM_CONN_PARAM_NRR: + rc = ble_ll_conn_hci_param_nrr(cmdbuf, len, rspbuf, rsplen); + break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) + case BLE_HCI_OCF_LE_SET_DATA_LEN: + rc = ble_ll_conn_hci_set_data_len(cmdbuf, len, rspbuf, rsplen); + break; + case BLE_HCI_OCF_LE_RD_SUGG_DEF_DATA_LEN: + if (len == 0) { + rc = ble_ll_hci_le_rd_sugg_data_len(rspbuf, rsplen); + } + break; + case BLE_HCI_OCF_LE_WR_SUGG_DEF_DATA_LEN: + rc = ble_ll_hci_le_wr_sugg_data_len(cmdbuf, len); + break; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + case BLE_HCI_OCF_LE_ADD_RESOLV_LIST: + rc = ble_ll_resolv_list_add(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_RMV_RESOLV_LIST: + rc = ble_ll_resolv_list_rmv(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_CLR_RESOLV_LIST: + if (len == 0) { + rc = ble_ll_resolv_list_clr(); + } + break; + case BLE_HCI_OCF_LE_RD_RESOLV_LIST_SIZE: + if (len == 0) { + rc = ble_ll_resolv_list_read_size(rspbuf, rsplen); + } + break; + case BLE_HCI_OCF_LE_RD_PEER_RESOLV_ADDR: + rc = ble_ll_resolv_peer_addr_rd(cmdbuf, len, rspbuf, rsplen); + break; + case BLE_HCI_OCF_LE_RD_LOCAL_RESOLV_ADDR: + rc = ble_ll_resolv_local_addr_rd(cmdbuf, len, rspbuf, rsplen); + break; + case BLE_HCI_OCF_LE_SET_ADDR_RES_EN: + rc = ble_ll_resolv_enable_cmd(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_SET_RPA_TMO: + rc = ble_ll_resolv_set_rpa_tmo(cmdbuf, len); + break; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) + case BLE_HCI_OCF_LE_RD_MAX_DATA_LEN: + if (len == 0) { + rc = ble_ll_hci_le_rd_max_data_len(rspbuf, rsplen); + } + break; +#endif +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + case BLE_HCI_OCF_LE_RD_PHY: + rc = ble_ll_conn_hci_le_rd_phy(cmdbuf, len, rspbuf, rsplen); + break; + case BLE_HCI_OCF_LE_SET_DEFAULT_PHY: + rc = ble_ll_hci_le_set_def_phy(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_SET_PHY: + rc = ble_ll_conn_hci_le_set_phy(cmdbuf, len); + break; +#endif +#if MYNEWT_VAL(BLE_LL_DTM) + case BLE_HCI_OCF_LE_RX_TEST_V2: + rc = ble_ll_hci_dtm_rx_test_v2(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_TX_TEST_V2: + rc = ble_ll_hci_dtm_tx_test_v2(cmdbuf, len); + break; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + case BLE_HCI_OCF_LE_SET_ADV_SET_RND_ADDR: + rc = ble_ll_adv_hci_set_random_addr(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_SET_EXT_ADV_PARAM: + rc = ble_ll_adv_ext_set_param(cmdbuf, len, rspbuf, rsplen); + break; + case BLE_HCI_OCF_LE_SET_EXT_ADV_DATA: + rc = ble_ll_adv_ext_set_adv_data(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_SET_EXT_SCAN_RSP_DATA: + rc = ble_ll_adv_ext_set_scan_rsp(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_SET_EXT_ADV_ENABLE: + rc = ble_ll_adv_ext_set_enable(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_RD_MAX_ADV_DATA_LEN: + if (len == 0) { + rc = ble_ll_adv_rd_max_adv_data_len(rspbuf, rsplen); + } + break; + case BLE_HCI_OCF_LE_RD_NUM_OF_ADV_SETS: + if (len == 0) { + rc = ble_ll_adv_rd_sup_adv_sets(rspbuf, rsplen); + } + break; + case BLE_HCI_OCF_LE_REMOVE_ADV_SET: + rc = ble_ll_adv_remove(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_CLEAR_ADV_SETS: + if (len == 0) { + rc = ble_ll_adv_clear_all(); + } + break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + case BLE_HCI_OCF_LE_SET_PERIODIC_ADV_PARAMS: + rc = ble_ll_adv_periodic_set_param(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_SET_PERIODIC_ADV_DATA: + rc = ble_ll_adv_periodic_set_data(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_SET_PERIODIC_ADV_ENABLE: + rc = ble_ll_adv_periodic_enable(cmdbuf, len); + break; +#endif +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + case BLE_HCI_OCF_LE_SET_EXT_SCAN_PARAM: + rc = ble_ll_set_ext_scan_params(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_SET_EXT_SCAN_ENABLE: + rc = ble_ll_hci_ext_scan_set_enable(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_EXT_CREATE_CONN: + rc = ble_ll_ext_conn_create(cmdbuf, len); + break; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + case BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC: + rc = ble_ll_sync_create(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC_CANCEL: + if (len == 0) { + rc = ble_ll_sync_cancel(cb); + } + break; + case BLE_HCI_OCF_LE_PERIODIC_ADV_TERM_SYNC: + rc = ble_ll_sync_terminate(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_ADD_DEV_TO_PERIODIC_ADV_LIST: + rc = ble_ll_sync_list_add(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_REM_DEV_FROM_PERIODIC_ADV_LIST: + rc = ble_ll_sync_list_remove(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_CLEAR_PERIODIC_ADV_LIST: + if (len == 0) { + rc = ble_ll_sync_list_clear(); + } + break; + case BLE_HCI_OCF_LE_RD_PERIODIC_ADV_LIST_SIZE: + if (len == 0) { + rc = ble_ll_sync_list_size(rspbuf, rsplen); + } + break; +#if MYNEWT_VAL(BLE_VERSION) >= 51 + case BLE_HCI_OCF_LE_PERIODIC_ADV_RECEIVE_ENABLE: + rc = ble_ll_sync_receive_enable(cmdbuf, len); + break; +#endif +#endif + case BLE_HCI_OCF_LE_RD_TRANSMIT_POWER: + rc = ble_ll_read_tx_power(rspbuf, rsplen); + break; + case BLE_HCI_OCF_LE_RD_RF_PATH_COMPENSATION: + rc = ble_ll_read_rf_path_compensation(rspbuf, rsplen); + break; + case BLE_HCI_OCF_LE_WR_RF_PATH_COMPENSATION: + rc = ble_ll_write_rf_path_compensation(cmdbuf, len); + break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + case BLE_HCI_OCF_LE_SET_PRIVACY_MODE: + rc = ble_ll_resolve_set_priv_mode(cmdbuf, len); + break; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) + case BLE_HCI_OCF_LE_PERIODIC_ADV_SYNC_TRANSFER: + rc = ble_ll_sync_transfer(cmdbuf, len, rspbuf, rsplen); + break; + case BLE_HCI_OCF_LE_PERIODIC_ADV_SET_INFO_TRANSFER: + rc = ble_ll_adv_periodic_set_info_transfer(cmdbuf, len, rspbuf, rsplen); + break; + case BLE_HCI_OCF_LE_PERIODIC_ADV_SYNC_TRANSFER_PARAMS: + rc = ble_ll_set_sync_transfer_params(cmdbuf, len, rspbuf, rsplen); + break; + case BLE_HCI_OCF_LE_SET_DEFAULT_SYNC_TRANSFER_PARAMS: + rc = ble_ll_set_default_sync_transfer_params(cmdbuf, len); + break; +#endif +#if MYNEWT_VAL(BLE_VERSION) >= 52 + case BLE_HCI_OCF_LE_SET_HOST_FEAT: + rc = ble_ll_set_host_feat(cmdbuf, len); + break; +#endif + default: + rc = BLE_ERR_UNKNOWN_HCI_CMD; + break; + } + + /* + * This code is here because we add 256 to the return code to denote + * that the reply to this command should be command status (as opposed to + * command complete). + * + * For unknown HCI command let us return always command status as per + * specification Bluetooth 5, Vol. 2, Chapter 4.4 + */ + if (ble_ll_hci_le_cmd_send_cmd_status(ocf) || rc == BLE_ERR_UNKNOWN_HCI_CMD) { + rc += (BLE_ERR_MAX + 1); + } + + return rc; +} + +/** + * Process a link control command sent from the host to the controller. The HCI + * command has a 3 byte command header followed by data. The header is: + * -> opcode (2 bytes) + * -> Length of parameters (1 byte; does include command header bytes). + * + * @param cmdbuf Pointer to command buffer. Points to start of command header. + * @param ocf Opcode command field. + * + * @return int This function returns a BLE error code. If a command status + * event should be returned as opposed to command complete, + * 256 gets added to the return value. + */ +static int +ble_ll_hci_link_ctrl_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf) +{ + int rc; + + switch (ocf) { + case BLE_HCI_OCF_DISCONNECT_CMD: + rc = ble_ll_conn_hci_disconnect_cmd(cmdbuf, len); + /* Send command status instead of command complete */ + rc += (BLE_ERR_MAX + 1); + break; + + case BLE_HCI_OCF_RD_REM_VER_INFO: + rc = ble_ll_conn_hci_rd_rem_ver_cmd(cmdbuf, len); + /* Send command status instead of command complete */ + rc += (BLE_ERR_MAX + 1); + break; + + default: + rc = BLE_ERR_UNKNOWN_HCI_CMD; + break; + } + + return rc; +} + +static int +ble_ll_hci_cb_set_event_mask(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_cb_set_event_mask_cp *cmd = (const void *) cmdbuf; + + if (len != sizeof (*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + g_ble_ll_hci_event_mask = le64toh(cmd->event_mask); + + return BLE_ERR_SUCCESS; +} + +static int +ble_ll_hci_cb_set_event_mask2(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_cb_set_event_mask2_cp *cmd = (const void *) cmdbuf; + + if (len != sizeof (*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + g_ble_ll_hci_event_mask2 = le64toh(cmd->event_mask2); + + return BLE_ERR_SUCCESS; +} + +static int +ble_ll_hci_ctlr_bb_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, + uint8_t *rspbuf, uint8_t *rsplen) +{ + int rc; + + /* Assume error; if all pass rc gets set to 0 */ + rc = BLE_ERR_INV_HCI_CMD_PARMS; + + switch (ocf) { + case BLE_HCI_OCF_CB_SET_EVENT_MASK: + rc = ble_ll_hci_cb_set_event_mask(cmdbuf, len); + break; + case BLE_HCI_OCF_CB_RESET: + if (len == 0) { + rc = ble_ll_reset(); + } + break; + case BLE_HCI_OCF_CB_SET_EVENT_MASK2: + rc = ble_ll_hci_cb_set_event_mask2(cmdbuf, len); + break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) + case BLE_HCI_OCF_CB_RD_AUTH_PYLD_TMO: + rc = ble_ll_conn_hci_rd_auth_pyld_tmo(cmdbuf, len, rspbuf, rsplen); + break; + case BLE_HCI_OCF_CB_WR_AUTH_PYLD_TMO: + rc = ble_ll_conn_hci_wr_auth_pyld_tmo(cmdbuf, len, rspbuf, rsplen); + break; +#endif + default: + rc = BLE_ERR_UNKNOWN_HCI_CMD; + break; + } + + return rc; +} + +static int +ble_ll_hci_info_params_cmd_proc(const uint8_t *cmdbuf, uint8_t len, + uint16_t ocf, uint8_t *rspbuf, uint8_t *rsplen) +{ + int rc; + + /* Assume error; if all pass rc gets set to 0 */ + rc = BLE_ERR_INV_HCI_CMD_PARMS; + + switch (ocf) { + case BLE_HCI_OCF_IP_RD_LOCAL_VER: + if (len == 0) { + rc = ble_ll_hci_rd_local_version(rspbuf, rsplen); + } + break; + case BLE_HCI_OCF_IP_RD_LOC_SUPP_CMD: + if (len == 0) { + rc = ble_ll_hci_rd_local_supp_cmd(rspbuf, rsplen); + } + break; + case BLE_HCI_OCF_IP_RD_LOC_SUPP_FEAT: + if (len == 0) { + rc = ble_ll_hci_rd_local_supp_feat(rspbuf, rsplen); + } + break; + case BLE_HCI_OCF_IP_RD_BD_ADDR: + if (len == 0) { + rc = ble_ll_hci_rd_bd_addr(rspbuf, rsplen); + } + break; + default: + rc = BLE_ERR_UNKNOWN_HCI_CMD; + break; + } + + return rc; +} + +static int +ble_ll_hci_status_params_cmd_proc(const uint8_t *cmdbuf, uint8_t len, + uint16_t ocf, uint8_t *rspbuf, + uint8_t *rsplen) +{ + int rc; + + switch (ocf) { + case BLE_HCI_OCF_RD_RSSI: + rc = ble_ll_conn_hci_rd_rssi(cmdbuf, len, rspbuf, rsplen); + break; + default: + rc = BLE_ERR_UNKNOWN_HCI_CMD; + break; + } + + return rc; +} + +/** + * Called to process an HCI command from the host. + * + * @param ev Pointer to os event containing a pointer to command buffer + */ +static void +ble_ll_hci_cmd_proc(struct ble_npl_event *ev) +{ + int rc; + uint8_t ogf; + uint8_t rsplen; + struct ble_hci_cmd *cmd; + uint16_t opcode; + uint16_t ocf; + ble_ll_hci_post_cmd_complete_cb post_cb = NULL; + struct ble_hci_ev *hci_ev; + struct ble_hci_ev_command_status *cmd_status; + struct ble_hci_ev_command_complete *cmd_complete; + uint8_t *rspbuf; + + BLE_LL_DEBUG_GPIO(HCI_CMD, 1); + + /* The command buffer is the event argument */ + cmd = ble_npl_event_get_arg(ev); + BLE_LL_ASSERT(cmd != NULL); + + /* Get the opcode from the command buffer */ + opcode = le16toh(cmd->opcode); + ocf = BLE_HCI_OCF(opcode); + ogf = BLE_HCI_OGF(opcode); + + /* + * The command response pointer points into the same buffer as the + * command data itself. That is fine, as each command reads all the data + * before crafting a response. + * Also reuse cmd buffer for complete event + */ + hci_ev = (struct ble_hci_ev *) cmd; + rspbuf = hci_ev->data + sizeof(*cmd_complete); + + /* Assume response length is zero */ + rsplen = 0; + + switch (ogf) { + case BLE_HCI_OGF_LINK_CTRL: + rc = ble_ll_hci_link_ctrl_cmd_proc(cmd->data, cmd->length, ocf); + break; + case BLE_HCI_OGF_CTLR_BASEBAND: + rc = ble_ll_hci_ctlr_bb_cmd_proc(cmd->data, cmd->length, ocf, rspbuf, &rsplen); + break; + case BLE_HCI_OGF_INFO_PARAMS: + rc = ble_ll_hci_info_params_cmd_proc(cmd->data, cmd->length, ocf, rspbuf, &rsplen); + break; + case BLE_HCI_OGF_STATUS_PARAMS: + rc = ble_ll_hci_status_params_cmd_proc(cmd->data, cmd->length, ocf, rspbuf, &rsplen); + break; + case BLE_HCI_OGF_LE: + rc = ble_ll_hci_le_cmd_proc(cmd->data, cmd->length, ocf, rspbuf, &rsplen, &post_cb); + break; + default: + /* XXX: Need to support other OGF. For now, return unsupported */ + rc = BLE_ERR_UNKNOWN_HCI_CMD; + break; + } + + /* If no response is generated, we free the buffers */ + BLE_LL_ASSERT(rc >= 0); + if (rc <= BLE_ERR_MAX) { + /* Create a command complete event with status from command */ + hci_ev->opcode = BLE_HCI_EVCODE_COMMAND_COMPLETE; + hci_ev->length = sizeof(*cmd_complete) + rsplen; + + cmd_complete = (void *) hci_ev->data; + cmd_complete->num_packets = ble_ll_hci_get_num_cmd_pkts(); + cmd_complete->opcode = htole16(opcode); + cmd_complete->status = (uint8_t) rc; + } else { + /* Create a command status event */ + rc -= (BLE_ERR_MAX + 1); + + hci_ev->opcode = BLE_HCI_EVCODE_COMMAND_STATUS; + hci_ev->length = sizeof(*cmd_status); + + cmd_status = (void *) hci_ev->data; + cmd_status->status = (uint8_t)rc; + cmd_status->num_packets = ble_ll_hci_get_num_cmd_pkts(); + cmd_status->opcode = htole16(opcode); + } + + /* Count commands and those in error */ + if (rc) { + STATS_INC(ble_ll_stats, hci_cmd_errs); + } else { + STATS_INC(ble_ll_stats, hci_cmds); + } + + /* Send the event (events cannot be masked) */ + ble_ll_hci_event_send(hci_ev); + + /* Call post callback if set by command handler */ + if (post_cb) { + post_cb(); + } + + BLE_LL_DEBUG_GPIO(HCI_CMD, 0); +} + +/** + * Sends an HCI command to the controller. On success, the supplied buffer is + * relinquished to the controller task. On failure, the caller must free the + * buffer. + * + * @param cmd A flat buffer containing the HCI command to + * send. + * + * @return 0 on success; + * BLE_ERR_MEM_CAPACITY on HCI buffer exhaustion. + */ +int +ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg) +{ + struct ble_npl_event *ev; + + /* Get an event structure off the queue */ + ev = &g_ble_ll_hci_cmd_ev; + if (ble_npl_event_is_queued(ev)) { + return BLE_ERR_MEM_CAPACITY; + } + + /* Fill out the event and post to Link Layer */ + ble_npl_event_set_arg(ev, cmd); + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, ev); + + return 0; +} + +/* Send ACL data from host to contoller */ +int +ble_ll_hci_acl_rx(struct os_mbuf *om, void *arg) +{ + ble_ll_acl_data_in(om); + return 0; +} + +/** + * Initalize the LL HCI. + * + * NOTE: This function is called by the HCI RESET command so if any code + * is added here it must be OK to be executed when the reset command is used. + */ +void +ble_ll_hci_init(void) +{ + BLE_LL_DEBUG_GPIO_INIT(HCI_CMD); + BLE_LL_DEBUG_GPIO_INIT(HCI_EV); + + /* Set event callback for command processing */ + ble_npl_event_init(&g_ble_ll_hci_cmd_ev, ble_ll_hci_cmd_proc, NULL); + + /* Set defaults for LE events: Vol 2 Part E 7.8.1 */ + g_ble_ll_hci_le_event_mask = 0x1f; + + /* Set defaults for controller/baseband events: Vol 2 Part E 7.3.1 */ + g_ble_ll_hci_event_mask = 0x1fffffffffff; + + + /* Set page 2 to 0 */ + g_ble_ll_hci_event_mask2 = 0; + + /* reset RF path compensation values */ + rx_path_pwr_compensation = 0; + tx_path_pwr_compensation = 0; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + /* after reset both legacy and extended advertising commands are allowed */ + hci_adv_mode = ADV_MODE_ANY; +#endif +} + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_hci_ev.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_hci_ev.c new file mode 100644 index 000000000..b78b919ef --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_hci_ev.c @@ -0,0 +1,526 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef ESP_PLATFORM + +#include +#include +#include +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/include/nimble/hci_common.h" +#include "nimble/nimble/include/nimble/ble_hci_trans.h" +#include "../include/controller/ble_ll.h" +#include "../include/controller/ble_ll_hci.h" +#include "../include/controller/ble_ll_ctrl.h" +#include "ble_ll_conn_priv.h" + +#if (BLETEST_CONCURRENT_CONN_TEST == 1) +extern void bletest_ltk_req_reply(uint16_t handle); +#endif + +/** + * Send a data length change event for a connection to the host. + * + * @param connsm Pointer to connection state machine + */ +void +ble_ll_hci_ev_datalen_chg(struct ble_ll_conn_sm *connsm) +{ + struct ble_hci_ev_le_subev_data_len_chg *ev; + struct ble_hci_ev *hci_ev; + + if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_DATA_LEN_CHG)) { + hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (hci_ev) { + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*ev); + ev = (void *) hci_ev->data; + + ev->subev_code = BLE_HCI_LE_SUBEV_DATA_LEN_CHG; + ev->conn_handle = htole16(connsm->conn_handle); + + ev->max_tx_octets = htole16(connsm->eff_max_tx_octets); + ev->max_tx_time = htole16(connsm->eff_max_tx_time); + ev->max_rx_octets = htole16(connsm->eff_max_rx_octets); + ev->max_rx_time = htole16(connsm->eff_max_rx_time); + + ble_ll_hci_event_send(hci_ev); + } + } +} + +/** + * Send a connection parameter request event for a connection to the host. + * + * @param connsm Pointer to connection state machine + */ +void +ble_ll_hci_ev_rem_conn_parm_req(struct ble_ll_conn_sm *connsm, + struct ble_ll_conn_params *cp) +{ + struct ble_hci_ev_le_subev_rem_conn_param_req *ev; + struct ble_hci_ev *hci_ev; + + if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_REM_CONN_PARM_REQ)) { + hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (hci_ev) { + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*ev); + ev = (void *) hci_ev->data; + + ev->subev_code = BLE_HCI_LE_SUBEV_REM_CONN_PARM_REQ; + ev->conn_handle = htole16(connsm->conn_handle); + ev->min_interval = htole16(cp->interval_min); + ev->max_interval = htole16(cp->interval_max); + ev->latency = htole16(cp->latency); + ev->timeout = htole16(cp->timeout); + + ble_ll_hci_event_send(hci_ev); + } + } +} + +/** + * Send a connection update event. + * + * @param connsm Pointer to connection state machine + * @param status The error code. + */ +void +ble_ll_hci_ev_conn_update(struct ble_ll_conn_sm *connsm, uint8_t status) +{ + struct ble_hci_ev_le_subev_conn_upd_complete *ev; + struct ble_hci_ev *hci_ev; + + if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_CONN_UPD_COMPLETE)) { + hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (hci_ev) { + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*ev); + ev = (void *) hci_ev->data; + + ev->subev_code = BLE_HCI_LE_SUBEV_CONN_UPD_COMPLETE; + ev->status = status; + ev->conn_handle = htole16(connsm->conn_handle); + ev->conn_itvl = htole16(connsm->conn_itvl); + ev->conn_latency = htole16(connsm->slave_latency); + ev->supervision_timeout = htole16(connsm->supervision_tmo); + + ble_ll_hci_event_send(hci_ev); + } + } +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) +void +ble_ll_hci_ev_encrypt_chg(struct ble_ll_conn_sm *connsm, uint8_t status) +{ + struct ble_hci_ev_enc_key_refresh *ev_key_refresh; + struct ble_hci_ev_enrypt_chg *ev_enc_chf; + struct ble_hci_ev *hci_ev; + + if (CONN_F_ENC_CHANGE_SENT(connsm) == 0) { + if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_ENCRYPT_CHG)) { + hci_ev = (void *)ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (hci_ev) { + hci_ev->opcode = BLE_HCI_EVCODE_ENCRYPT_CHG; + hci_ev->length = sizeof(*ev_enc_chf); + ev_enc_chf = (void *) hci_ev->data; + + ev_enc_chf->status = status; + ev_enc_chf->connection_handle = htole16(connsm->conn_handle); + ev_enc_chf->enabled = (status == BLE_ERR_SUCCESS) ? 0x01 : 0x00; + + ble_ll_hci_event_send(hci_ev); + } + } + + CONN_F_ENC_CHANGE_SENT(connsm) = 1; + return; + } + + if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_ENC_KEY_REFRESH)) { + hci_ev = (void *)ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (hci_ev) { + hci_ev->opcode = BLE_HCI_EVCODE_ENC_KEY_REFRESH; + hci_ev->length = sizeof(*ev_key_refresh); + ev_key_refresh = (void *) hci_ev->data; + + ev_key_refresh->status = status; + ev_key_refresh->conn_handle = htole16(connsm->conn_handle); + + ble_ll_hci_event_send(hci_ev); + } + } +} + +/** + * Send a long term key request event for a connection to the host. + * + * @param connsm Pointer to connection state machine + */ +int +ble_ll_hci_ev_ltk_req(struct ble_ll_conn_sm *connsm) +{ + struct ble_hci_ev_le_subev_lt_key_req *ev; + struct ble_hci_ev *hci_ev; + int rc; + + if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_LT_KEY_REQ)) { + hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (hci_ev) { + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*ev); + ev = (void *) hci_ev->data; + + ev->subev_code = BLE_HCI_LE_SUBEV_LT_KEY_REQ; + ev->conn_handle = htole16(connsm->conn_handle); + ev->rand = htole64(connsm->enc_data.host_rand_num); + ev->div = htole16(connsm->enc_data.enc_div); + + ble_ll_hci_event_send(hci_ev); + } + rc = 0; + } else { + rc = -1; + } + +#if (BLETEST_CONCURRENT_CONN_TEST == 1) + if (rc == 0) { + bletest_ltk_req_reply(connsm->conn_handle); + } +#endif + return rc; +} +#endif + +void +ble_ll_hci_ev_rd_rem_used_feat(struct ble_ll_conn_sm *connsm, uint8_t status) +{ + struct ble_hci_ev_le_subev_rd_rem_used_feat *ev; + struct ble_hci_ev *hci_ev; + + if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_RD_REM_USED_FEAT)) { + hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (hci_ev) { + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*ev); + ev = (void *) hci_ev->data; + + ev->subev_code = BLE_HCI_LE_SUBEV_RD_REM_USED_FEAT; + ev->status = status; + ev->conn_handle = htole16(connsm->conn_handle); + ev->features[0] = connsm->conn_features; + memcpy(ev->features + 1, connsm->remote_features, 7); + + ble_ll_hci_event_send(hci_ev); + } + } +} + +void +ble_ll_hci_ev_rd_rem_ver(struct ble_ll_conn_sm *connsm, uint8_t status) +{ + struct ble_hci_ev_rd_rem_ver_info_cmp *ev; + struct ble_hci_ev *hci_ev; + + if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_RD_REM_VER_INFO_CMP)) { + hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (hci_ev) { + hci_ev->opcode = BLE_HCI_EVCODE_RD_REM_VER_INFO_CMP; + hci_ev->length = sizeof(*ev); + ev = (void *) hci_ev->data; + + ev->status = status; + ev->conn_handle = htole16(connsm->conn_handle); + ev->version = connsm->vers_nr; + ev->manufacturer = htole16(connsm->comp_id); + ev->subversion = htole16(connsm->sub_vers_nr); + + ble_ll_hci_event_send(hci_ev); + } + } +} + +/** + * Send a HW error to the host. + * + * @param hw_err + * + * @return int 0: event masked or event sent, -1 otherwise + */ +int +ble_ll_hci_ev_hw_err(uint8_t hw_err) +{ + struct ble_hci_ev_hw_error *ev; + struct ble_hci_ev *hci_ev; + int rc; + + rc = 0; + if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_HW_ERROR)) { + hci_ev = (void *)ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (hci_ev) { + hci_ev->opcode = BLE_HCI_EVCODE_HW_ERROR; + hci_ev->length = sizeof(*ev); + ev = (void *) hci_ev->data; + + ev->hw_code = hw_err; + + ble_ll_hci_event_send(hci_ev); + } else { + rc = -1; + } + } + return rc; +} + +void +ble_ll_hci_ev_databuf_overflow(void) +{ + struct ble_hci_ev_data_buf_overflow *ev; + struct ble_hci_ev *hci_ev; + + if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_DATA_BUF_OVERFLOW)) { + hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (hci_ev) { + hci_ev->opcode = BLE_HCI_EVCODE_DATA_BUF_OVERFLOW; + hci_ev->length = sizeof(*ev); + ev = (void *) hci_ev->data; + + ev->link_type = BLE_HCI_EVENT_ACL_BUF_OVERFLOW; + + ble_ll_hci_event_send(hci_ev); + } + } +} + +/** + * Send a LE Channel Selection Algorithm event. + * + * @param connsm Pointer to connection state machine + */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) +void +ble_ll_hci_ev_le_csa(struct ble_ll_conn_sm *connsm) +{ + struct ble_hci_ev_le_subev_chan_sel_alg *ev; + struct ble_hci_ev *hci_ev; + + if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_CHAN_SEL_ALG)) { + hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (hci_ev) { + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*ev); + ev = (void *) hci_ev->data; + + ev->subev_code = BLE_HCI_LE_SUBEV_CHAN_SEL_ALG; + ev->conn_handle = htole16(connsm->conn_handle); + ev->csa = connsm->csmflags.cfbit.csa2_supp ? 0x01 : 0x00; + + ble_ll_hci_event_send(hci_ev); + } + } +} +#endif + +/** + * Sends the LE Scan Request Received event + * + */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +void +ble_ll_hci_ev_send_scan_req_recv(uint8_t adv_handle, const uint8_t *peer, + uint8_t peer_addr_type) +{ + struct ble_hci_ev_le_subev_scan_req_rcvd *ev; + struct ble_hci_ev *hci_ev; + + if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_SCAN_REQ_RCVD)) { + hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (hci_ev) { + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*ev); + ev = (void *) hci_ev->data; + + ev->subev_code = BLE_HCI_LE_SUBEV_SCAN_REQ_RCVD; + ev->adv_handle = adv_handle; + ev->peer_addr_type = peer_addr_type; + memcpy(ev->peer_addr, peer, BLE_DEV_ADDR_LEN); + + ble_ll_hci_event_send(hci_ev); + } + } +} +#endif + +/** + * Sends the LE Scan Timeout Event + * + */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +void +ble_ll_hci_ev_send_scan_timeout(void) +{ + struct ble_hci_ev_le_subev_scan_timeout *ev; + struct ble_hci_ev *hci_ev; + + if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_SCAN_TIMEOUT)) { + hci_ev = (void *)ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (hci_ev) { + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*ev); + ev = (void *) hci_ev->data; + + ev->subev_code = BLE_HCI_LE_SUBEV_SCAN_TIMEOUT; + + ble_ll_hci_event_send(hci_ev); + } + } +} +#endif + +/** + * Sends the LE Advertising Set Terminated event + * + */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +void +ble_ll_hci_ev_send_adv_set_terminated(uint8_t status, uint8_t adv_handle, + uint16_t conn_handle, uint8_t events) +{ + struct ble_hci_ev_le_subev_adv_set_terminated *ev; + struct ble_hci_ev *hci_ev; + + if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_ADV_SET_TERMINATED)) { + hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (hci_ev) { + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*ev); + ev = (void *) hci_ev->data; + + ev->subev_code = BLE_HCI_LE_SUBEV_ADV_SET_TERMINATED; + ev->status = status; + ev->adv_handle = adv_handle; + ev->conn_handle = htole16(conn_handle); + ev->num_events = events; + + ble_ll_hci_event_send(hci_ev); + } + } +} +#endif + +/** + * Send a PHY update complete event + * + * @param connsm Pointer to connection state machine + * @param status error status of event + */ +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +int +ble_ll_hci_ev_phy_update(struct ble_ll_conn_sm *connsm, uint8_t status) +{ + struct ble_hci_ev_le_subev_phy_update_complete *ev; + struct ble_hci_ev *hci_ev; + int rc; + + rc = 0; + if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_PHY_UPDATE_COMPLETE)) { + hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (hci_ev) { + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*ev); + ev = (void *) hci_ev->data; + + ev->subev_code = BLE_HCI_LE_SUBEV_PHY_UPDATE_COMPLETE; + ev->status = status; + ev->conn_handle = htole16(connsm->conn_handle); + ev->tx_phy = connsm->phy_data.cur_tx_phy; + ev->rx_phy = connsm->phy_data.cur_rx_phy; + + ble_ll_hci_event_send(hci_ev); + } else { + rc = BLE_ERR_MEM_CAPACITY; + } + } + return rc; +} +#endif + +void +ble_ll_hci_ev_send_vendor_err(const char *file, uint32_t line) +{ + struct ble_hci_ev_vendor_debug *ev; + struct ble_hci_ev *hci_ev; + unsigned int str_len; + bool skip = true; + uint8_t digit; + int max_len; + int i; + + /* 6 is for line number ":00000" , we assume files have no more than 64k of + * lines + */ + max_len = BLE_HCI_MAX_DATA_LEN - sizeof(*ev) - 6; + + hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (hci_ev) { + hci_ev->opcode = BLE_HCI_EVCODE_VENDOR_DEBUG; + hci_ev->length = sizeof(*ev); + ev = (void *) hci_ev->data; + + /* Debug id for future use */ + ev->id = 0x00; + + /* snprintf would be nicer but this is heavy on flash + * len = snprintf((char *) ev->data, max_len, "%s:%u", file, line); + * if (len < 0) { + * len = 0; + * } else if (len > max_len) { + * len = max_len; + * } + * + * hci_ev->length += len; + */ + str_len = strlen(file); + if (str_len > max_len) { + str_len = max_len; + } + + memcpy(ev->data, file, str_len); + ev->data[str_len++] = ':'; + + for (i = 100000; i >= 10; i /= 10) { + digit = (line % i) / (i/10); + + if (!digit && skip) { + continue; + } + + skip = false; + ev->data[str_len++] = '0' + digit; + } + + hci_ev->length += str_len; + + ble_ll_hci_event_send(hci_ev); + } +} + +#endif \ No newline at end of file diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_uuid_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_priv.h similarity index 54% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_uuid_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_priv.h index 3dbcc6b8e..900950ef6 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_uuid_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_priv.h @@ -17,29 +17,35 @@ * under the License. */ -#ifndef H_BLE_UUID_PRIV_ -#define H_BLE_UUID_PRIV_ - -#include "host/ble_uuid.h" +#ifndef H_BLE_LL_PRIV_ +#define H_BLE_LL_PRIV_ #ifdef __cplusplus extern "C" { #endif -struct os_mbuf; +#ifdef MYNEWT -int ble_uuid_init_from_att_mbuf(ble_uuid_any_t *uuid, struct os_mbuf *om, - int off, int len); -int ble_uuid_init_from_att_buf(ble_uuid_any_t *uuid, const void *buf, - size_t len); +#include "syscfg/syscfg.h" +#include "hal/hal_gpio.h" -int ble_uuid_to_any(const ble_uuid_t *uuid, ble_uuid_any_t *uuid_any); -int ble_uuid_to_mbuf(const ble_uuid_t *uuid, struct os_mbuf *om); -int ble_uuid_flat(const ble_uuid_t *uuid, void *dst); -int ble_uuid_length(const ble_uuid_t *uuid); +#define BLE_LL_DEBUG_GPIO_INIT(_name) \ + if (MYNEWT_VAL(BLE_LL_DEBUG_GPIO_ ## _name) >= 0) { \ + hal_gpio_init_out(MYNEWT_VAL(BLE_LL_DEBUG_GPIO_ ## _name), 0); \ + } + +#define BLE_LL_DEBUG_GPIO(_name, _val) \ + if (MYNEWT_VAL(BLE_LL_DEBUG_GPIO_ ## _name) >= 0) { \ + hal_gpio_write(MYNEWT_VAL(BLE_LL_DEBUG_GPIO_ ## _name), !!(_val)); \ + } + +#else +#define BLE_LL_DEBUG_GPIO_INIT(_name) (void)(0) +#define BLE_LL_DEBUG_GPIO(_name, _val) (void)(0) +#endif #ifdef __cplusplus } #endif -#endif +#endif /* H_BLE_LL_PRIV_ */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_rand.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_rand.c new file mode 100644 index 000000000..dd89e04b0 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_rand.c @@ -0,0 +1,188 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef ESP_PLATFORM + +#include +#include +#include +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/include/nimble/nimble_opt.h" +#include "../include/controller/ble_hw.h" +#include "../include/controller/ble_ll.h" +#if MYNEWT_VAL(TRNG) +#include "trng/trng.h" +#endif + +#if MYNEWT_VAL(TRNG) +static struct trng_dev *g_trng; +#else +/* This is a simple circular buffer for holding N samples of random data */ +struct ble_ll_rnum_data +{ + uint8_t *rnd_in; + uint8_t *rnd_out; + volatile uint8_t rnd_size; +}; + +struct ble_ll_rnum_data g_ble_ll_rnum_data; +uint8_t g_ble_ll_rnum_buf[MYNEWT_VAL(BLE_LL_RNG_BUFSIZE)]; + +#define IS_RNUM_BUF_END(x) \ + (x == &g_ble_ll_rnum_buf[MYNEWT_VAL(BLE_LL_RNG_BUFSIZE) - 1]) + +void +ble_ll_rand_sample(uint8_t rnum) +{ + os_sr_t sr; + + OS_ENTER_CRITICAL(sr); + if (g_ble_ll_rnum_data.rnd_size < MYNEWT_VAL(BLE_LL_RNG_BUFSIZE)) { + ++g_ble_ll_rnum_data.rnd_size; + g_ble_ll_rnum_data.rnd_in[0] = rnum; + if (IS_RNUM_BUF_END(g_ble_ll_rnum_data.rnd_in)) { + g_ble_ll_rnum_data.rnd_in = g_ble_ll_rnum_buf; + } else { + ++g_ble_ll_rnum_data.rnd_in; + } + } else { + /* Stop generating random numbers as we are full */ + ble_hw_rng_stop(); + } + OS_EXIT_CRITICAL(sr); +} +#endif + +/* Get 'len' bytes of random data */ +int +ble_ll_rand_data_get(uint8_t *buf, uint8_t len) +{ +#if MYNEWT_VAL(TRNG) + size_t num; + + while (len) { + num = trng_read(g_trng, buf, len); + buf += num; + len -= num; + } +#else + uint8_t rnums; + os_sr_t sr; + + while (len != 0) { + OS_ENTER_CRITICAL(sr); + rnums = g_ble_ll_rnum_data.rnd_size; + if (rnums > len) { + rnums = len; + } + len -= rnums; + g_ble_ll_rnum_data.rnd_size -= rnums; + while (rnums) { + buf[0] = g_ble_ll_rnum_data.rnd_out[0]; + if (IS_RNUM_BUF_END(g_ble_ll_rnum_data.rnd_out)) { + g_ble_ll_rnum_data.rnd_out = g_ble_ll_rnum_buf; + } else { + ++g_ble_ll_rnum_data.rnd_out; + } + ++buf; + --rnums; + } + OS_EXIT_CRITICAL(sr); + + /* Make sure rng is started! */ + ble_hw_rng_start(); + + /* Wait till bytes are in buffer. */ + if (len) { + while ((g_ble_ll_rnum_data.rnd_size < len) && + (g_ble_ll_rnum_data.rnd_size < MYNEWT_VAL(BLE_LL_RNG_BUFSIZE))) { + /* Spin here */ + } + } + } +#endif + return BLE_ERR_SUCCESS; +} + +/** + * Called to obtain a "prand" as defined in core V4.2 Vol 6 Part B 1.3.2.2 + * + * @param prand + */ +void +ble_ll_rand_prand_get(uint8_t *prand) +{ + uint16_t sum; + + while (1) { + /* Get 24 bits of random data */ + ble_ll_rand_data_get(prand, 3); + + /* Prand cannot be all zeros or 1's. */ + sum = prand[0] + prand[1] + prand[2]; + if ((sum != 0) && (sum != (3 * 0xff))) { + break; + } + } + + /* Upper two bits must be 01 */ + prand[2] &= ~0xc0; + prand[2] |= 0x40; +} + +/** + * Start the generation of random numbers + * + * @return int + */ +int +ble_ll_rand_start(void) +{ +#if MYNEWT_VAL(TRNG) + /* Nothing to do - this is handled by driver */ +#else + /* Start the generation of numbers if we are not full */ + if (g_ble_ll_rnum_data.rnd_size < MYNEWT_VAL(BLE_LL_RNG_BUFSIZE)) { + ble_hw_rng_start(); + } +#endif + return 0; +} + +/** + * Initialize LL random number generation. Should be called only once on + * initialization. + * + * @return int + */ +int +ble_ll_rand_init(void) +{ +#if MYNEWT_VAL(TRNG) + g_trng = (struct trng_dev *) os_dev_open("trng", OS_TIMEOUT_NEVER, NULL); +#else + g_ble_ll_rnum_data.rnd_in = g_ble_ll_rnum_buf; + g_ble_ll_rnum_data.rnd_out = g_ble_ll_rnum_buf; + ble_hw_rng_init(ble_ll_rand_sample, 1); +#endif + return 0; +} + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_resolv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_resolv.c new file mode 100644 index 000000000..231ecad23 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_resolv.c @@ -0,0 +1,755 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef ESP_PLATFORM + +#include +#include +#include +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/include/nimble/nimble_opt.h" +#include "../include/controller/ble_ll.h" +#include "../include/controller/ble_ll_resolv.h" +#include "../include/controller/ble_ll_hci.h" +#include "../include/controller/ble_ll_scan.h" +#include "../include/controller/ble_ll_adv.h" +#include "../include/controller/ble_ll_sync.h" +#include "../include/controller/ble_hw.h" +#include "ble_ll_conn_priv.h" + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) +struct ble_ll_resolv_data +{ + uint8_t addr_res_enabled; + uint8_t rl_size; + uint8_t rl_cnt_hw; + uint8_t rl_cnt; + ble_npl_time_t rpa_tmo; + struct ble_npl_callout rpa_timer; +}; +struct ble_ll_resolv_data g_ble_ll_resolv_data; + +__attribute__((aligned(4))) +struct ble_ll_resolv_entry g_ble_ll_resolv_list[MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE)]; + +static int +ble_ll_is_controller_busy(void) +{ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + if (ble_ll_sync_enabled()) { + return 1; + } +#endif + + return ble_ll_adv_enabled() || ble_ll_scan_enabled() || + g_ble_ll_conn_create_sm; +} +/** + * Called to determine if a change is allowed to the resolving list at this + * time. We are not allowed to modify the resolving list if address translation + * is enabled and we are either scanning, advertising, or attempting to create + * a connection. + * + * @return int 0: not allowed. 1: allowed. + */ +static int +ble_ll_resolv_list_chg_allowed(void) +{ + int rc; + + if (g_ble_ll_resolv_data.addr_res_enabled && + ble_ll_is_controller_busy()) { + rc = 0; + } else { + rc = 1; + } + return rc; +} + + +/** + * Called to generate a resolvable private address in rl structure + * + * @param rl + * @param local + */ +static void +ble_ll_resolv_gen_priv_addr(struct ble_ll_resolv_entry *rl, int local) +{ + uint8_t *irk; + uint8_t *prand; + struct ble_encryption_block ecb; + uint8_t *addr; + + BLE_LL_ASSERT(rl != NULL); + + if (local) { + addr = rl->rl_local_rpa; + irk = rl->rl_local_irk; + } else { + addr = rl->rl_peer_rpa; + irk = rl->rl_peer_irk; + } + + /* Get prand */ + prand = addr + 3; + ble_ll_rand_prand_get(prand); + + /* Calculate hash, hash = ah(local IRK, prand) */ + memcpy(ecb.key, irk, 16); + memset(ecb.plain_text, 0, 13); + ecb.plain_text[13] = prand[2]; + ecb.plain_text[14] = prand[1]; + ecb.plain_text[15] = prand[0]; + + /* Calculate hash */ + ble_hw_encrypt_block(&ecb); + + addr[0] = ecb.cipher_text[15]; + addr[1] = ecb.cipher_text[14]; + addr[2] = ecb.cipher_text[13]; +} + +/** + * Called when the Resolvable private address timer expires. This timer + * is used to regenerate local and peers RPA's in the resolving list. + */ +static void +ble_ll_resolv_rpa_timer_cb(struct ble_npl_event *ev) +{ + int i; + os_sr_t sr; + struct ble_ll_resolv_entry *rl; + + rl = &g_ble_ll_resolv_list[0]; + for (i = 0; i < g_ble_ll_resolv_data.rl_cnt; ++i) { + if (rl->rl_has_local) { + OS_ENTER_CRITICAL(sr); + ble_ll_resolv_gen_priv_addr(rl, 1); + OS_EXIT_CRITICAL(sr); + } + + if (rl->rl_has_peer) { + OS_ENTER_CRITICAL(sr); + ble_ll_resolv_gen_priv_addr(rl, 0); + OS_EXIT_CRITICAL(sr); + } + ++rl; + } + + ble_npl_callout_reset(&g_ble_ll_resolv_data.rpa_timer, + g_ble_ll_resolv_data.rpa_tmo); + + ble_ll_adv_rpa_timeout(); +} + +/** + * Called to determine if the IRK is all zero. + * + * @param irk + * + * @return int 0: IRK is zero . 1: IRK has non-zero value. + */ +static int +ble_ll_resolv_irk_nonzero(const uint8_t *irk) +{ + int i; + int rc; + + rc = 0; + for (i = 0; i < 16; ++i) { + if (*irk != 0) { + rc = 1; + break; + } + ++irk; + } + + return rc; +} + +/** + * Clear the resolving list + * + * @return int 0: success, BLE error code otherwise + */ +int +ble_ll_resolv_list_clr(void) +{ + /* Check proper state */ + if (!ble_ll_resolv_list_chg_allowed()) { + return BLE_ERR_CMD_DISALLOWED; + } + + /* Sets total on list to 0. Clears HW resolve list */ + g_ble_ll_resolv_data.rl_cnt_hw = 0; + g_ble_ll_resolv_data.rl_cnt = 0; + ble_hw_resolv_list_clear(); + + /* stop RPA timer when clearing RL */ + ble_npl_callout_stop(&g_ble_ll_resolv_data.rpa_timer); + + return BLE_ERR_SUCCESS; +} + +/** + * Read the size of the resolving list. This is the total number of resolving + * list entries allowed by the controller. + * + * @param rspbuf Pointer to response buffer + * + * @return int 0: success. + */ +int +ble_ll_resolv_list_read_size(uint8_t *rspbuf, uint8_t *rsplen) +{ + struct ble_hci_le_rd_resolv_list_size_rp *rsp = (void *) rspbuf; + + rsp->size = g_ble_ll_resolv_data.rl_size; + + *rsplen = sizeof(*rsp); + return BLE_ERR_SUCCESS; +} + +/** + * Used to determine if the device is on the resolving list. + * + * @param addr + * @param addr_type Public address (0) or random address (1) + * + * @return int 0: device is not on resolving list; otherwise the return value + * is the 'position' of the device in the resolving list (the index of the + * element plus 1). + */ +static int +ble_ll_is_on_resolv_list(const uint8_t *addr, uint8_t addr_type) +{ + int i; + struct ble_ll_resolv_entry *rl; + + rl = &g_ble_ll_resolv_list[0]; + for (i = 0; i < g_ble_ll_resolv_data.rl_cnt; ++i) { + if ((rl->rl_addr_type == addr_type) && + (!memcmp(&rl->rl_identity_addr[0], addr, BLE_DEV_ADDR_LEN))) { + return i + 1; + } + ++rl; + } + + return 0; +} + +/** + * Used to determine if the device is on the resolving list. + * + * @param addr + * @param addr_type Public address (0) or random address (1) + * + * @return Pointer to resolving list entry or NULL if no entry found. + */ +struct ble_ll_resolv_entry * +ble_ll_resolv_list_find(const uint8_t *addr, uint8_t addr_type) +{ + int i; + struct ble_ll_resolv_entry *rl; + + rl = &g_ble_ll_resolv_list[0]; + for (i = 0; i < g_ble_ll_resolv_data.rl_cnt; ++i) { + if ((rl->rl_addr_type == addr_type) && + (!memcmp(&rl->rl_identity_addr[0], addr, BLE_DEV_ADDR_LEN))) { + return rl; + } + ++rl; + } + + return NULL; +} + +/** + * Add a device to the resolving list + * + * @return int + */ +int +ble_ll_resolv_list_add(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_add_resolv_list_cp *cmd = (const void *) cmdbuf; + struct ble_ll_resolv_entry *rl; + int rc = BLE_ERR_SUCCESS; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Must be in proper state */ + if (!ble_ll_resolv_list_chg_allowed()) { + return BLE_ERR_CMD_DISALLOWED; + } + + /* Check if we have any open entries */ + if (g_ble_ll_resolv_data.rl_cnt >= g_ble_ll_resolv_data.rl_size) { + return BLE_ERR_MEM_CAPACITY; + } + + /* spec is not clear on how to handle this but make sure host is aware + * that new keys are not used in that case + */ + if (ble_ll_is_on_resolv_list(cmd->peer_id_addr, cmd->peer_addr_type)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* we keep this sorted in a way that entries with peer_irk are first */ + if (ble_ll_resolv_irk_nonzero(cmd->peer_irk)) { + memmove(&g_ble_ll_resolv_list[g_ble_ll_resolv_data.rl_cnt_hw + 1], + &g_ble_ll_resolv_list[g_ble_ll_resolv_data.rl_cnt_hw], + (g_ble_ll_resolv_data.rl_cnt - g_ble_ll_resolv_data.rl_cnt_hw) * + sizeof(g_ble_ll_resolv_list[0])); + rl = &g_ble_ll_resolv_list[g_ble_ll_resolv_data.rl_cnt_hw]; + } else { + rl = &g_ble_ll_resolv_list[g_ble_ll_resolv_data.rl_cnt]; + } + + memset (rl, 0, sizeof(*rl)); + rl->rl_addr_type = cmd->peer_addr_type; + memcpy(rl->rl_identity_addr, cmd->peer_id_addr, BLE_DEV_ADDR_LEN); + + if (ble_ll_resolv_irk_nonzero(cmd->peer_irk)) { + swap_buf(rl->rl_peer_irk, cmd->peer_irk, 16); + rl->rl_has_peer = 1; + + /* generate peer RPA now, those will be updated by timer when + * resolution is enabled + */ + ble_ll_resolv_gen_priv_addr(rl, 0); + } + + if (ble_ll_resolv_irk_nonzero(cmd->local_irk)) { + swap_buf(rl->rl_local_irk, cmd->local_irk, 16); + rl->rl_has_local = 1; + + /* generate local RPA now, those will be updated by timer when + * resolution is enabled + */ + ble_ll_resolv_gen_priv_addr(rl, 1); + } + + /* By default use privacy network mode */ + rl->rl_priv_mode = BLE_HCI_PRIVACY_NETWORK; + + /* Add peers IRKs to HW resolving list. Should always succeed since we + * already checked if there is room for it. + */ + if (rl->rl_has_peer) { + rc = ble_hw_resolv_list_add(rl->rl_peer_irk); + BLE_LL_ASSERT(rc == BLE_ERR_SUCCESS); + g_ble_ll_resolv_data.rl_cnt_hw++; + } + + g_ble_ll_resolv_data.rl_cnt++; + + /* start RPA timer if this was first element added to RL */ + if (g_ble_ll_resolv_data.rl_cnt == 1) { + ble_npl_callout_reset(&g_ble_ll_resolv_data.rpa_timer, + g_ble_ll_resolv_data.rpa_tmo); + } + + return rc; +} + +/** + * Remove a device from the resolving list + * + * @param cmdbuf + * + * @return int 0: success, BLE error code otherwise + */ +int +ble_ll_resolv_list_rmv(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_rmv_resolve_list_cp *cmd = (const void *) cmdbuf; + int position; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Must be in proper state */ + if (!ble_ll_resolv_list_chg_allowed()) { + return BLE_ERR_CMD_DISALLOWED; + } + + /* Remove from IRK records */ + position = ble_ll_is_on_resolv_list(cmd->peer_id_addr, cmd->peer_addr_type); + if (position) { + BLE_LL_ASSERT(position <= g_ble_ll_resolv_data.rl_cnt); + + memmove(&g_ble_ll_resolv_list[position - 1], + &g_ble_ll_resolv_list[position], + (g_ble_ll_resolv_data.rl_cnt - position) * + sizeof(g_ble_ll_resolv_list[0])); + g_ble_ll_resolv_data.rl_cnt--; + + /* Remove from HW list */ + if (position <= g_ble_ll_resolv_data.rl_cnt_hw) { + ble_hw_resolv_list_rmv(position - 1); + g_ble_ll_resolv_data.rl_cnt_hw--; + } + + /* stop RPA timer if list is empty */ + if (g_ble_ll_resolv_data.rl_cnt == 0) { + ble_npl_callout_stop(&g_ble_ll_resolv_data.rpa_timer); + } + + return BLE_ERR_SUCCESS; + } + + return BLE_ERR_UNK_CONN_ID; +} + +/** + * Called to enable or disable address resolution in the controller + * + * @param cmdbuf + * + * @return int + */ +int +ble_ll_resolv_enable_cmd(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_set_addr_res_en_cp *cmd = (const void *) cmdbuf; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (ble_ll_is_controller_busy()) { + return BLE_ERR_CMD_DISALLOWED; + + } + + if (cmd->enable > 1) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + g_ble_ll_resolv_data.addr_res_enabled = cmd->enable; + + return BLE_ERR_SUCCESS; +} + +int +ble_ll_resolv_peer_addr_rd(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_le_rd_peer_recolv_addr_cp *cmd = (const void *) cmdbuf; + struct ble_hci_le_rd_peer_recolv_addr_rp *rsp = (void *) rspbuf; + struct ble_ll_resolv_entry *rl; + int rc; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + rl = ble_ll_resolv_list_find(cmd->peer_id_addr, cmd->peer_addr_type); + if (rl) { + memcpy(rsp->rpa, rl->rl_peer_rpa, BLE_DEV_ADDR_LEN); + rc = BLE_ERR_SUCCESS; + } else { + memset(rsp->rpa, 0, BLE_DEV_ADDR_LEN); + rc = BLE_ERR_UNK_CONN_ID; + } + + *rsplen = sizeof(*rsp); + return rc; +} + +int +ble_ll_resolv_local_addr_rd(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_le_rd_local_recolv_addr_cp *cmd = (const void *) cmdbuf; + struct ble_hci_le_rd_local_recolv_addr_rp *rsp = (void *) rspbuf; + struct ble_ll_resolv_entry *rl; + int rc; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + rl = ble_ll_resolv_list_find(cmd->peer_id_addr, cmd->peer_addr_type); + if (rl) { + memcpy(rsp->rpa, rl->rl_local_rpa, BLE_DEV_ADDR_LEN); + rc = BLE_ERR_SUCCESS; + } else { + memset(rsp->rpa, 0, BLE_DEV_ADDR_LEN); + rc = BLE_ERR_UNK_CONN_ID; + } + + *rsplen = sizeof(*rsp); + return rc; +} + +/** + * Set the resolvable private address timeout. + * + * @param cmdbuf + * + * @return int + */ +int +ble_ll_resolv_set_rpa_tmo(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_set_rpa_tmo_cp *cmd = (const void *)cmdbuf; + uint16_t tmo_secs; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + tmo_secs = le16toh(cmd->rpa_timeout); + if (!((tmo_secs > 0) && (tmo_secs <= 0xA1B8))) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + g_ble_ll_resolv_data.rpa_tmo = ble_npl_time_ms_to_ticks32(tmo_secs * 1000); + + /* restart timer if there is something on RL */ + if (g_ble_ll_resolv_data.rl_cnt) { + ble_npl_callout_reset(&g_ble_ll_resolv_data.rpa_timer, + g_ble_ll_resolv_data.rpa_tmo); + } + + return BLE_ERR_SUCCESS; +} + +int +ble_ll_resolve_set_priv_mode(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_set_privacy_mode_cp *cmd = (const void *) cmdbuf; + struct ble_ll_resolv_entry *rl; + + if (ble_ll_is_controller_busy()) { + return BLE_ERR_CMD_DISALLOWED; + } + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + rl = ble_ll_resolv_list_find(cmd->peer_id_addr, cmd->peer_id_addr_type); + if (!rl) { + return BLE_ERR_UNK_CONN_ID; + } + + if (cmd->mode > BLE_HCI_PRIVACY_DEVICE) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + rl->rl_priv_mode = cmd->mode; + + return BLE_ERR_SUCCESS; +} + +/** + * Returns the Resolvable Private address timeout, in os ticks + * + * + * @return uint32_t + */ +uint32_t +ble_ll_resolv_get_rpa_tmo(void) +{ + return g_ble_ll_resolv_data.rpa_tmo; +} + +void +ble_ll_resolv_get_priv_addr(struct ble_ll_resolv_entry *rl, int local, + uint8_t *addr) +{ + os_sr_t sr; + + BLE_LL_ASSERT(rl != NULL); + BLE_LL_ASSERT(addr != NULL); + + OS_ENTER_CRITICAL(sr); + if (local) { + BLE_LL_ASSERT(rl->rl_has_local); + memcpy(addr, rl->rl_local_rpa, BLE_DEV_ADDR_LEN); + } else { + BLE_LL_ASSERT(rl->rl_has_peer); + memcpy(addr, rl->rl_peer_rpa, BLE_DEV_ADDR_LEN); + } + + OS_EXIT_CRITICAL(sr); +} + +void +ble_ll_resolv_set_peer_rpa(int index, uint8_t *rpa) +{ + os_sr_t sr; + struct ble_ll_resolv_entry *rl; + + OS_ENTER_CRITICAL(sr); + rl = &g_ble_ll_resolv_list[index]; + memcpy(rl->rl_peer_rpa, rpa, BLE_DEV_ADDR_LEN); + OS_EXIT_CRITICAL(sr); +} + +void +ble_ll_resolv_set_local_rpa(int index, uint8_t *rpa) +{ + os_sr_t sr; + struct ble_ll_resolv_entry *rl; + + OS_ENTER_CRITICAL(sr); + rl = &g_ble_ll_resolv_list[index]; + memcpy(rl->rl_local_rpa, rpa, BLE_DEV_ADDR_LEN); + OS_EXIT_CRITICAL(sr); +} + +/** + * Generate a resolvable private address. + * + * @param addr + * @param addr_type + * @param rpa + * + * @return int + */ +int +ble_ll_resolv_gen_rpa(uint8_t *addr, uint8_t addr_type, uint8_t *rpa, int local) +{ + struct ble_ll_resolv_entry *rl; + + rl = ble_ll_resolv_list_find(addr, addr_type); + if (rl) { + if ((local && rl->rl_has_local) || (!local && rl->rl_has_peer)) { + ble_ll_resolv_get_priv_addr(rl, local, rpa); + return 1; + } + } + + return 0; +} + +/** + * Resolve a Resolvable Private Address + * + * @param rpa + * @param index + * + * @return int + */ +int +ble_ll_resolv_rpa(const uint8_t *rpa, const uint8_t *irk) +{ + int rc; + const uint32_t *irk32; + uint32_t *key32; + uint32_t *pt32; + struct ble_encryption_block ecb; + + irk32 = (const uint32_t *)irk; + key32 = (uint32_t *)&ecb.key[0]; + + key32[0] = irk32[0]; + key32[1] = irk32[1]; + key32[2] = irk32[2]; + key32[3] = irk32[3]; + + pt32 = (uint32_t *)&ecb.plain_text[0]; + pt32[0] = 0; + pt32[1] = 0; + pt32[2] = 0; + pt32[3] = 0; + + ecb.plain_text[15] = rpa[3]; + ecb.plain_text[14] = rpa[4]; + ecb.plain_text[13] = rpa[5]; + + ble_hw_encrypt_block(&ecb); + if ((ecb.cipher_text[15] == rpa[0]) && (ecb.cipher_text[14] == rpa[1]) && + (ecb.cipher_text[13] == rpa[2])) { + rc = 1; + } else { + rc = 0; + } + + return rc; +} + +int +ble_ll_resolv_peer_rpa_any(const uint8_t *rpa) +{ + int i; + + for (i = 0; i < g_ble_ll_resolv_data.rl_cnt_hw; i++) { + if (ble_ll_resolv_rpa(rpa, g_ble_ll_resolv_list[i].rl_peer_irk)) { + return i; + } + } + + return -1; +} + +/** + * Returns whether or not address resolution is enabled. + * + * @return uint8_t + */ +uint8_t +ble_ll_resolv_enabled(void) +{ + return g_ble_ll_resolv_data.addr_res_enabled; +} + +/** + * Called to reset private address resolution module. + */ +void +ble_ll_resolv_list_reset(void) +{ + g_ble_ll_resolv_data.addr_res_enabled = 0; + ble_npl_callout_stop(&g_ble_ll_resolv_data.rpa_timer); + ble_ll_resolv_list_clr(); + ble_ll_resolv_init(); +} + +void +ble_ll_resolv_init(void) +{ + uint8_t hw_size; + + /* Default is 15 minutes */ + g_ble_ll_resolv_data.rpa_tmo = ble_npl_time_ms_to_ticks32(15 * 60 * 1000); + + hw_size = ble_hw_resolv_list_size(); + if (hw_size > MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE)) { + hw_size = MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE); + } + g_ble_ll_resolv_data.rl_size = hw_size; + + ble_npl_callout_init(&g_ble_ll_resolv_data.rpa_timer, + &g_ble_ll_data.ll_evq, + ble_ll_resolv_rpa_timer_cb, + NULL); +} + +#endif /* if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) */ +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_rfmgmt.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_rfmgmt.c new file mode 100644 index 000000000..444019cc0 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_rfmgmt.c @@ -0,0 +1,348 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef ESP_PLATFORM + +#include +#include +#include +#include +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/os/os_cputime.h" +#include "../include/controller/ble_phy.h" +#include "../include/controller/ble_ll.h" +#include "../include/controller/ble_ll_sched.h" +#include "../include/controller/ble_ll_rfmgmt.h" + +#if MYNEWT_VAL(BLE_LL_RFMGMT_ENABLE_TIME) > 0 + +enum ble_ll_rfmgmt_state { + RFMGMT_STATE_OFF = 0, + RFMGMT_STATE_ENABLING = 1, + RFMGMT_STATE_ENABLED = 2, +}; + +struct ble_ll_rfmgmt_data { + enum ble_ll_rfmgmt_state state; + uint16_t ticks_to_enabled; + + struct hal_timer timer; + bool timer_scheduled; + uint32_t timer_scheduled_at; + + bool enable_scan; + bool enable_sched; + uint32_t enable_scan_at; + uint32_t enable_sched_at; + + uint32_t enabled_at; + + struct ble_npl_event release_ev; +}; + +static struct ble_ll_rfmgmt_data g_ble_ll_rfmgmt_data; + +static void +ble_ll_rfmgmt_enable(void) +{ + OS_ASSERT_CRITICAL(); + + if (g_ble_ll_rfmgmt_data.state == RFMGMT_STATE_OFF) { + g_ble_ll_rfmgmt_data.state = RFMGMT_STATE_ENABLING; + g_ble_ll_rfmgmt_data.enabled_at = os_cputime_get32(); + ble_phy_rfclk_enable(); + } +} + +static void +ble_ll_rfmgmt_disable(void) +{ + OS_ASSERT_CRITICAL(); + + if (g_ble_ll_rfmgmt_data.state != RFMGMT_STATE_OFF) { + ble_phy_rfclk_disable(); + g_ble_ll_rfmgmt_data.state = RFMGMT_STATE_OFF; + } +} + +static void +ble_ll_rfmgmt_timer_reschedule(void) +{ + struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data; + uint32_t enable_at; + + /* Figure out when we need to enable RF */ + if (rfmgmt->enable_scan && rfmgmt->enable_sched) { + if (CPUTIME_LT(rfmgmt->enable_scan_at, rfmgmt->enable_sched_at)) { + enable_at = rfmgmt->enable_scan_at; + } else { + enable_at = rfmgmt->enable_sched_at; + } + } else if (rfmgmt->enable_scan) { + enable_at = rfmgmt->enable_scan_at; + } else if (rfmgmt->enable_sched) { + enable_at = rfmgmt->enable_sched_at; + } else { + rfmgmt->timer_scheduled = false; + os_cputime_timer_stop(&rfmgmt->timer); + return; + } + + if (rfmgmt->timer_scheduled) { + /* + * If there is timer already scheduled at the same time we do not need + * to do anything. Otherwise we need to stop timer and schedule it again + * regardless if it's earlier or later to make sure it fires at the time + * something expects it. + */ + + if (rfmgmt->timer_scheduled_at == enable_at) { + return; + } + + rfmgmt->timer_scheduled = false; + os_cputime_timer_stop(&rfmgmt->timer); + } + + /* + * In case timer was requested to be enabled before current time, just make + * sure it's enabled and assume caller can deal with this. This will happen + * if something is scheduled "now" since "enable_at" is in the past, but in + * such case it's absolutely harmless since we already have clock enabled + * and this will do nothing. + */ + if (CPUTIME_LEQ(enable_at, os_cputime_get32())) { + ble_ll_rfmgmt_enable(); + return; + } + + rfmgmt->timer_scheduled = true; + rfmgmt->timer_scheduled_at = enable_at; + os_cputime_timer_start(&rfmgmt->timer, enable_at); +} + +static void +ble_ll_rfmgmt_timer_exp(void *arg) +{ + g_ble_ll_rfmgmt_data.timer_scheduled = false; + ble_ll_rfmgmt_enable(); +} + +static void +ble_ll_rfmgmt_release_ev(struct ble_npl_event *ev) +{ + struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data; + uint32_t now; + bool can_disable; + uint8_t lls; + os_sr_t sr; + + OS_ENTER_CRITICAL(sr); + + now = os_cputime_get32(); + + can_disable = true; + lls = ble_ll_state_get(); + + if (rfmgmt->enable_scan && CPUTIME_GEQ(now, rfmgmt->enable_scan_at)) { + /* Blocked by scan */ + can_disable = false; + } else if (rfmgmt->enable_sched && CPUTIME_GEQ(now, rfmgmt->enable_sched_at)) { + /* Blocked by scheduler item */ + can_disable = false; + } else if (lls != BLE_LL_STATE_STANDBY) { + /* Blocked by LL state */ + can_disable = false; + } + + if (can_disable) { + ble_ll_rfmgmt_disable(); + } + + OS_EXIT_CRITICAL(sr); +} + +static uint32_t +ble_ll_rfmgmt_ticks_to_enabled(void) +{ + struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data; + uint32_t rem_ticks; + uint32_t now; + + switch (rfmgmt->state) { + case RFMGMT_STATE_OFF: + rem_ticks = rfmgmt->ticks_to_enabled; + break; + case RFMGMT_STATE_ENABLING: + now = os_cputime_get32(); + if (CPUTIME_LT(now, rfmgmt->enabled_at + rfmgmt->ticks_to_enabled)) { + rem_ticks = rfmgmt->enabled_at + rfmgmt->ticks_to_enabled - now; + break; + } + rfmgmt->state = RFMGMT_STATE_ENABLED; + /* no break */ + case RFMGMT_STATE_ENABLED: + rem_ticks = 0; + break; + default: + BLE_LL_ASSERT(0); + rem_ticks = 0; + break; + } + + return rem_ticks; +} + +void +ble_ll_rfmgmt_init(void) +{ + struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data; + + rfmgmt->state = RFMGMT_STATE_OFF; + + rfmgmt->ticks_to_enabled = + ble_ll_usecs_to_ticks_round_up(MYNEWT_VAL(BLE_LL_RFMGMT_ENABLE_TIME)); + + rfmgmt->timer_scheduled = false; + os_cputime_timer_init(&rfmgmt->timer, ble_ll_rfmgmt_timer_exp, NULL); + + ble_npl_event_init(&rfmgmt->release_ev, ble_ll_rfmgmt_release_ev, NULL); +} + +void +ble_ll_rfmgmt_reset(void) +{ + struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data; + + rfmgmt->timer_scheduled = false; + rfmgmt->timer_scheduled_at = 0; + os_cputime_timer_stop(&rfmgmt->timer); + + ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &rfmgmt->release_ev); + + ble_ll_rfmgmt_disable(); + + rfmgmt->enable_scan = false; + rfmgmt->enable_scan_at = 0; + rfmgmt->enable_sched = false; + rfmgmt->enable_sched_at = 0; + + rfmgmt->enabled_at = 0; +} + +void +ble_ll_rfmgmt_scan_changed(bool enabled, uint32_t next_window) +{ + struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data; + os_sr_t sr; + + OS_ENTER_CRITICAL(sr); + + rfmgmt->enable_scan = enabled; + rfmgmt->enable_scan_at = next_window - rfmgmt->ticks_to_enabled; + + ble_ll_rfmgmt_timer_reschedule(); + + OS_EXIT_CRITICAL(sr); +} + +void +ble_ll_rfmgmt_sched_changed(struct ble_ll_sched_item *first) +{ + struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data; + os_sr_t sr; + + OS_ENTER_CRITICAL(sr); + + rfmgmt->enable_sched = (first != NULL); + if (first) { + rfmgmt->enable_sched_at = first->start_time - rfmgmt->ticks_to_enabled; + } + + ble_ll_rfmgmt_timer_reschedule(); + + OS_EXIT_CRITICAL(sr); +} + +void +ble_ll_rfmgmt_release(void) +{ + struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data; + os_sr_t sr; + + OS_ENTER_CRITICAL(sr); + + ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &rfmgmt->release_ev); + + if (g_ble_ll_rfmgmt_data.state != RFMGMT_STATE_OFF) { + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &rfmgmt->release_ev); + } + + OS_EXIT_CRITICAL(sr); +} + +uint32_t +ble_ll_rfmgmt_enable_now(void) +{ + struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data; + uint32_t enabled_at; + os_sr_t sr; + + OS_ENTER_CRITICAL(sr); + + ble_ll_rfmgmt_enable(); + + if (rfmgmt->state == RFMGMT_STATE_ENABLED) { + enabled_at = os_cputime_get32(); + } else { + enabled_at = rfmgmt->enabled_at + rfmgmt->ticks_to_enabled + 1; + } + + OS_EXIT_CRITICAL(sr); + + return enabled_at; +} + +bool +ble_ll_rfmgmt_is_enabled(void) +{ + bool ret; + + OS_ASSERT_CRITICAL(); + + ret = ble_ll_rfmgmt_ticks_to_enabled() == 0; + + return ret; +} + +#else + +void +ble_ll_rfmgmt_init(void) +{ + static bool enabled = false; + + if (!enabled) { + ble_phy_rfclk_enable(); + } + + enabled = true; +} + +#endif +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_scan.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_scan.c new file mode 100644 index 000000000..03a683a76 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_scan.c @@ -0,0 +1,3981 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef ESP_PLATFORM + +#include +#include +#include +#include +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/porting/nimble/include/os/os_cputime.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/include/nimble/nimble_opt.h" +#include "nimble/nimble/include/nimble/hci_common.h" +#include "nimble/nimble/include/nimble/ble_hci_trans.h" +#include "../include/controller/ble_phy.h" +#include "../include/controller/ble_hw.h" +#include "../include/controller/ble_ll.h" +#include "../include/controller/ble_ll_sched.h" +#include "../include/controller/ble_ll_adv.h" +#include "../include/controller/ble_ll_scan.h" +#include "../include/controller/ble_ll_hci.h" +#include "../include/controller/ble_ll_whitelist.h" +#include "../include/controller/ble_ll_resolv.h" +#include "../include/controller/ble_ll_rfmgmt.h" +#include "../include/controller/ble_ll_trace.h" +#include "../include/controller/ble_ll_sync.h" +#include "ble_ll_conn_priv.h" + +/* + * XXX: + * 1) I think I can guarantee that we dont process things out of order if + * I send an event when a scan request is sent. The scan_rsp_pending flag + * code might be made simpler. + * + * 2) Interleave sending scan requests to different advertisers? I guess I need + * a list of advertisers to which I sent a scan request and have yet to + * receive a scan response from? Implement this. + */ + +/* Dont allow more than 255 of these entries */ +#if MYNEWT_VAL(BLE_LL_NUM_SCAN_RSP_ADVS) > 255 + #error "Cannot have more than 255 scan response entries!" +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) +#define SCAN_VALID_PHY_MASK (BLE_HCI_LE_PHY_1M_PREF_MASK | BLE_HCI_LE_PHY_CODED_PREF_MASK) +#else +#define SCAN_VALID_PHY_MASK (BLE_HCI_LE_PHY_1M_PREF_MASK) +#endif + +/* The scanning parameters set by host */ +static struct ble_ll_scan_params g_ble_ll_scan_params[BLE_LL_SCAN_PHY_NUMBER]; + +/* The scanning state machine global object */ +static struct ble_ll_scan_sm g_ble_ll_scan_sm; + +struct ble_ll_ext_adv_hdr +{ + uint8_t mode; + uint8_t hdr_len; + uint8_t hdr[0]; +}; + +struct ble_ll_scan_addr_data { + bool adva_present; + uint8_t adva_type; + uint8_t *adva; + uint8_t targeta_type; + uint8_t *targeta; + uint8_t adv_addr_type; + uint8_t *adv_addr; + struct ble_ll_resolv_entry *rl; +}; + +/* + * Structure used to store advertisers. This is used to limit sending scan + * requests to the same advertiser and also to filter duplicate events sent + * to the host. + */ +struct ble_ll_scan_advertisers +{ + uint16_t sc_adv_flags; + uint16_t adi; + struct ble_dev_addr adv_addr; +}; + +#define BLE_LL_SC_ADV_F_RANDOM_ADDR (0x01) +#define BLE_LL_SC_ADV_F_SCAN_RSP_RXD (0x02) +#define BLE_LL_SC_ADV_F_DIRECT_RPT_SENT (0x04) +#define BLE_LL_SC_ADV_F_ADV_RPT_SENT (0x08) +#define BLE_LL_SC_ADV_F_SCAN_RSP_SENT (0x10) + +/* Contains list of advertisers that we have heard scan responses from */ +static uint8_t g_ble_ll_scan_num_rsp_advs; +struct ble_ll_scan_advertisers +g_ble_ll_scan_rsp_advs[MYNEWT_VAL(BLE_LL_NUM_SCAN_RSP_ADVS)]; + +/* Duplicates filtering data */ +#define BLE_LL_SCAN_ENTRY_TYPE_LEGACY(addr_type) \ + ((addr_type) & 1) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +#define BLE_LL_SCAN_ENTRY_TYPE_EXT(addr_type, has_aux, is_anon, adi) \ + (((adi >> 8) & 0xF0) | (1 << 3) | (is_anon << 2) | (has_aux << 1) | ((addr_type) & 1)) +#endif + +#define BLE_LL_SCAN_DUP_F_ADV_REPORT_SENT (0x01) +#define BLE_LL_SCAN_DUP_F_DIR_ADV_REPORT_SENT (0x02) +#define BLE_LL_SCAN_DUP_F_SCAN_RSP_SENT (0x04) + +struct ble_ll_scan_dup_entry { + uint8_t type; /* entry type, see BLE_LL_SCAN_ENTRY_TYPE_* */ + uint8_t addr[6]; + uint8_t flags; /* use BLE_LL_SCAN_DUP_F_xxx */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + uint16_t adi; +#endif + TAILQ_ENTRY(ble_ll_scan_dup_entry) link; +}; + +static os_membuf_t g_scan_dup_mem[ OS_MEMPOOL_SIZE( + MYNEWT_VAL(BLE_LL_NUM_SCAN_DUP_ADVS), + sizeof(struct ble_ll_scan_dup_entry)) ]; +static struct os_mempool g_scan_dup_pool; +static TAILQ_HEAD(ble_ll_scan_dup_list, ble_ll_scan_dup_entry) g_scan_dup_list; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +#if MYNEWT_VAL(BLE_LL_EXT_ADV_AUX_PTR_CNT) != 0 +static os_membuf_t ext_scan_aux_mem[ OS_MEMPOOL_SIZE( + MYNEWT_VAL(BLE_LL_EXT_ADV_AUX_PTR_CNT), + sizeof (struct ble_ll_aux_data)) +]; +#else +#define ext_scan_aux_mem NULL +#endif + +static struct os_mempool ext_scan_aux_pool; + +static int ble_ll_scan_start(struct ble_ll_scan_sm *scansm, + struct ble_ll_sched_item *sch); + +static void +ble_ll_aux_scan_drop_event_cb(struct ble_npl_event *ev) +{ + struct ble_ll_aux_data *aux_data = ble_npl_event_get_arg(ev); + + ble_ll_scan_end_adv_evt(aux_data); + ble_ll_scan_aux_data_unref(aux_data); +} + +static void +ble_ll_aux_scan_drop(struct ble_ll_aux_data *aux_data) +{ + BLE_LL_ASSERT(aux_data); + + STATS_INC(ble_ll_stats, aux_scan_drop); + + ble_npl_event_init(&aux_data->ev, ble_ll_aux_scan_drop_event_cb, aux_data); + ble_ll_event_send(&aux_data->ev); +} + +static int +ble_ll_aux_scan_cb(struct ble_ll_sched_item *sch) +{ + struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; + uint8_t lls = ble_ll_state_get(); + uint32_t wfr_usec; + + STATS_INC(ble_ll_stats, aux_sched_cb); + + /* Drop the scheduled item if scan was disable or there is aux or scan + * response pending + */ + if (!scansm->scan_enabled || scansm->cur_aux_data || + scansm->scan_rsp_pending) { + ble_ll_aux_scan_drop(sch->cb_arg); + sch->cb_arg = NULL; + goto done; + } + + /* Check if there is no aux connect sent. If so drop the sched item */ + if (lls == BLE_LL_STATE_INITIATING && ble_ll_conn_init_pending_aux_conn_rsp()) { + ble_ll_aux_scan_drop(sch->cb_arg); + sch->cb_arg = NULL; + goto done; + } + + /* This function is called only when scanner is running. This can happen + * in 3 states: + * BLE_LL_STATE_SCANNING + * BLE_LL_STATE_INITIATING + * BLE_LL_STATE_STANDBY + */ + if (lls != BLE_LL_STATE_STANDBY) { + ble_phy_disable(); + ble_ll_state_set(BLE_LL_STATE_STANDBY); + } + + /* When doing RX for AUX pkt, cur_aux_data keeps valid aux data */ + scansm->cur_aux_data = sch->cb_arg; + sch->cb_arg = NULL; + BLE_LL_ASSERT(scansm->cur_aux_data != NULL); + scansm->cur_aux_data->scanning = 1; + + if (ble_ll_scan_start(scansm, sch)) { + ble_ll_scan_interrupted(scansm); + goto done; + } + + STATS_INC(ble_ll_stats, aux_fired_for_read); + + wfr_usec = scansm->cur_aux_data->offset_units ? 300 : 30; + ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_RX, 0, wfr_usec); + +done: + + return BLE_LL_SCHED_STATE_DONE; +} + +static int +ble_ll_scan_ext_adv_init(struct ble_ll_aux_data **aux_data) +{ + struct ble_ll_aux_data *e; + + e = os_memblock_get(&ext_scan_aux_pool); + if (!e) { + return -1; + } + + memset(e, 0, sizeof(*e)); + e->sch.sched_cb = ble_ll_aux_scan_cb; + e->sch.sched_type = BLE_LL_SCHED_TYPE_AUX_SCAN; + e->ref_cnt = 1; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + e->rpa_index = -1; +#endif + ble_ll_trace_u32x2(BLE_LL_TRACE_ID_AUX_REF, (uint32_t)e, e->ref_cnt); + + *aux_data = e; + STATS_INC(ble_ll_stats, aux_allocated); + + return 0; +} +#endif + +static inline uint32_t +ble_ll_scan_time_hci_to_ticks(uint16_t value) +{ + return os_cputime_usecs_to_ticks(value * BLE_HCI_SCAN_ITVL); +} + +/* See Vol 6 Part B Section 4.4.3.2. Active scanning backoff */ +static void +ble_ll_scan_req_backoff(struct ble_ll_scan_sm *scansm, int success) +{ + BLE_LL_ASSERT(scansm->backoff_count == 0); + BLE_LL_ASSERT(scansm->scan_rsp_pending == 0); + + if (success) { + scansm->scan_rsp_cons_fails = 0; + ++scansm->scan_rsp_cons_ok; + if (scansm->scan_rsp_cons_ok == 2) { + scansm->scan_rsp_cons_ok = 0; + if (scansm->upper_limit > 1) { + scansm->upper_limit >>= 1; + } + } + STATS_INC(ble_ll_stats, scan_req_txg); + } else { + scansm->scan_rsp_cons_ok = 0; + ++scansm->scan_rsp_cons_fails; + if (scansm->scan_rsp_cons_fails == 2) { + scansm->scan_rsp_cons_fails = 0; + if (scansm->upper_limit < 256) { + scansm->upper_limit <<= 1; + } + } + STATS_INC(ble_ll_stats, scan_req_txf); + } + + scansm->backoff_count = rand() & (scansm->upper_limit - 1); + ++scansm->backoff_count; + BLE_LL_ASSERT(scansm->backoff_count <= 256); +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) +static void +ble_ll_scan_refresh_nrpa(struct ble_ll_scan_sm *scansm) +{ + ble_npl_time_t now; + + now = ble_npl_time_get(); + if ((ble_npl_stime_t)(now - scansm->scan_nrpa_timer) >= 0) { + /* Generate new NRPA */ + ble_ll_rand_data_get(scansm->scan_nrpa, BLE_DEV_ADDR_LEN); + scansm->scan_nrpa[5] &= ~0xc0; + + /* We'll use the same timeout as for RPA rotation */ + scansm->scan_nrpa_timer = now + ble_ll_resolv_get_rpa_tmo(); + } +} +#endif + +static void +ble_ll_scan_req_pdu_prepare(struct ble_ll_scan_sm *scansm, + const uint8_t *adv_addr, uint8_t adv_addr_type, + struct ble_ll_resolv_entry *rl) +{ + uint8_t hdr_byte; + struct ble_ll_scan_pdu_data *pdu_data; + uint8_t *scana; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + uint8_t rpa[BLE_DEV_ADDR_LEN]; +#endif + + pdu_data = &scansm->pdu_data; + + /* Construct first PDU header byte */ + hdr_byte = BLE_ADV_PDU_TYPE_SCAN_REQ; + if (adv_addr_type) { + hdr_byte |= BLE_ADV_PDU_HDR_RXADD_RAND; + } + + /* Determine ScanA */ + if (scansm->own_addr_type & 0x01) { + hdr_byte |= BLE_ADV_PDU_HDR_TXADD_RAND; + scana = g_random_addr; + } else { + scana = g_dev_addr; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + if (scansm->own_addr_type & 0x02) { + /* + * If device is on RL and we have local IRK, we use RPA generated using + * that IRK as ScanA. Otherwise we use NRPA as ScanA to prevent our + * device from being tracked when doing an active scan (Core 5.1, Vol 6, + * Part B, section 6.3) + */ + if (rl && rl->rl_has_local) { + ble_ll_resolv_get_priv_addr(rl, 1, rpa); + scana = rpa; + } else { + ble_ll_scan_refresh_nrpa(scansm); + scana = scansm->scan_nrpa; + } + + hdr_byte |= BLE_ADV_PDU_HDR_TXADD_RAND; + } +#endif + + /* Save scan request data */ + pdu_data->hdr_byte = hdr_byte; + memcpy(pdu_data->scana, scana, BLE_DEV_ADDR_LEN); + memcpy(pdu_data->adva, adv_addr, BLE_DEV_ADDR_LEN); +} + +static uint8_t +ble_ll_scan_req_tx_pdu_cb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) +{ + struct ble_ll_scan_sm *scansm = pducb_arg; + struct ble_ll_scan_pdu_data *pdu_data = &scansm->pdu_data; + + memcpy(dptr, pdu_data->scana, BLE_DEV_ADDR_LEN); + memcpy(dptr + BLE_DEV_ADDR_LEN, pdu_data->adva, BLE_DEV_ADDR_LEN); + + *hdr_byte = pdu_data->hdr_byte; + + return BLE_DEV_ADDR_LEN * 2; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +/* if copy_from is provided new report is initialized with that instead of + * defaults + */ +static struct ble_hci_ev * +ble_ll_scan_get_ext_adv_report(struct ext_adv_report *copy_from) +{ + struct ble_hci_ev_le_subev_ext_adv_rpt *ev; + struct ext_adv_report *report; + struct ble_hci_ev *hci_ev; + + hci_ev = ( void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO); + if (!hci_ev) { + return NULL; + } + + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*ev) + sizeof(*report); + ev = (void *) hci_ev->data; + + memset(ev, 0, sizeof(*ev)); + ev->subev_code = BLE_HCI_LE_SUBEV_EXT_ADV_RPT; + /* We support only one report per event now */ + ev->num_reports = 1; + + report = ev->reports; + + if (copy_from) { + memcpy(report, copy_from, sizeof(*report)); + report->data_len = 0; + } else { + memset(report, 0, sizeof(*report)); + + report->pri_phy = BLE_PHY_1M; + /* Init SID with "Not available" which is 0xFF */ + report->sid = 0xFF; + /* Init TX Power with "Not available" which is 127 */ + report->tx_power = 127; + /* Init RSSI with "Not available" which is 127 */ + report->rssi = 127; + /* Init address type with "anonymous" which is 0xFF */ + report->addr_type = 0xFF; + } + + return hci_ev; +} + +static void +ble_ll_scan_send_truncated(struct ble_ll_aux_data *aux_data) +{ + struct ble_hci_ev_le_subev_ext_adv_rpt *ev; + struct ext_adv_report *report; + struct ble_hci_ev *hci_ev; + + if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) { + return; + } + + BLE_LL_ASSERT(aux_data); + + /* No need to send if we did not send any report or sent truncated already */ + if (!(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_ANY) || + (aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED)) { + return; + } + + BLE_LL_ASSERT(aux_data->evt); + hci_ev = aux_data->evt; + aux_data->evt = NULL; + + hci_ev->length = sizeof(*ev) + sizeof(*report); + + ev = (void *) hci_ev->data; + report = ev->reports; + + report->data_len = 0; + + report->evt_type = aux_data->evt_type; + report->evt_type |= BLE_HCI_ADV_DATA_STATUS_TRUNCATED; + + if (aux_data->flags & BLE_LL_AUX_HAS_ADVA) { + memcpy(report->addr, aux_data->adva, 6); + report->addr_type = aux_data->adva_type; + } + + if (aux_data->flags & BLE_LL_AUX_HAS_TARGETA) { + memcpy(report->dir_addr, aux_data->targeta, 6); + report->dir_addr_type = aux_data->targeta_type; + } + + report->sid = aux_data->adi >> 12; + ble_ll_hci_event_send(hci_ev); + + aux_data->flags_ll |= BLE_LL_AUX_FLAG_SCAN_ERROR; + aux_data->flags_ll |= BLE_LL_AUX_FLAG_HCI_SENT_ANY; + aux_data->flags_ll |= BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED; +} + +static int +ble_ll_scan_get_adi(struct ble_ll_aux_data *aux_data, uint16_t *adi) +{ + if (!aux_data || !(aux_data->flags & BLE_LL_AUX_HAS_ADI)) { + return -1; + } + + *adi = aux_data->adi; + + return 0; +} + +void +ble_ll_scan_end_adv_evt(struct ble_ll_aux_data *aux_data) +{ + /* Make sure we send report with 'truncated' data state if needed */ + ble_ll_scan_send_truncated(aux_data); +} +#endif + +static void +ble_ll_scan_clean_cur_aux_data(void) +{ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; + + /* If scanner was reading aux ptr, we need to clean it up */ + if (scansm->cur_aux_data) { + ble_ll_scan_end_adv_evt(scansm->cur_aux_data); + ble_ll_scan_aux_data_unref(scansm->cur_aux_data); + scansm->cur_aux_data = NULL; + } +#endif +} + +void +ble_ll_scan_halt(void) +{ + struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; + + ble_ll_scan_clean_cur_aux_data(); + + /* Update backoff if we failed to receive scan response */ + if (scansm->scan_rsp_pending) { + scansm->scan_rsp_pending = 0; + ble_ll_scan_req_backoff(scansm, 0); + } +} + +/** + * Checks to see if we have received a scan response from this advertiser. + * + * @param adv_addr Address of advertiser + * @param txadd TxAdd bit (0: public; random otherwise) + * + * @return int 0: have not received a scan response; 1 otherwise. + */ +static int +ble_ll_scan_have_rxd_scan_rsp(uint8_t *addr, uint8_t txadd, + uint8_t ext_adv, uint16_t adi) +{ + uint8_t num_advs; + struct ble_ll_scan_advertisers *adv; + + /* Do we have an address match? Must match address type */ + adv = &g_ble_ll_scan_rsp_advs[0]; + num_advs = g_ble_ll_scan_num_rsp_advs; + while (num_advs) { + if (!memcmp(&adv->adv_addr, addr, BLE_DEV_ADDR_LEN)) { + /* Address type must match */ + if (txadd) { + if (adv->sc_adv_flags & BLE_LL_SC_ADV_F_RANDOM_ADDR) { + if (ext_adv) { + if (adi == adv->adi) { + return 1; + } + goto next; + } + return 1; + } + } else { + if ((adv->sc_adv_flags & BLE_LL_SC_ADV_F_RANDOM_ADDR) == 0) { + if (ext_adv) { + if (adi == adv->adi) { + return 1; + } + goto next; + } + return 1; + } + } + } +next: + ++adv; + --num_advs; + } + + return 0; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +static void +ble_ll_scan_add_scan_rsp_adv(uint8_t *addr, uint8_t txadd, + uint8_t ext_adv, uint16_t adi) +{ + uint8_t num_advs; + struct ble_ll_scan_advertisers *adv; + + /* XXX: for now, if we dont have room, just leave */ + num_advs = g_ble_ll_scan_num_rsp_advs; + if (num_advs == MYNEWT_VAL(BLE_LL_NUM_SCAN_RSP_ADVS)) { + return; + } + + /* Check if address is already on the list */ + if (ble_ll_scan_have_rxd_scan_rsp(addr, txadd, ext_adv, adi)) { + return; + } + + /* Add the advertiser to the array */ + adv = &g_ble_ll_scan_rsp_advs[num_advs]; + memcpy(&adv->adv_addr, addr, BLE_DEV_ADDR_LEN); + adv->sc_adv_flags = BLE_LL_SC_ADV_F_SCAN_RSP_RXD; + if (txadd) { + adv->sc_adv_flags |= BLE_LL_SC_ADV_F_RANDOM_ADDR; + } + adv->adi = adi; + ++g_ble_ll_scan_num_rsp_advs; + + return; +} + +static int +ble_ll_hci_send_legacy_ext_adv_report(uint8_t evtype, + const uint8_t *addr, uint8_t addr_type, + uint8_t rssi, + uint8_t adv_data_len, + struct os_mbuf *adv_data, + const uint8_t *inita, uint8_t inita_type) +{ + struct ble_hci_ev_le_subev_ext_adv_rpt *ev; + struct ext_adv_report *report; + struct ble_hci_ev *hci_ev; + + if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) { + return -1; + } + + /* Drop packet if adv data doesn't fit */ + if ((sizeof(*ev) + sizeof(ev->reports[0]) + adv_data_len) > BLE_HCI_MAX_DATA_LEN) { + STATS_INC(ble_ll_stats, adv_evt_dropped); + return -1; + } + + hci_ev = ble_ll_scan_get_ext_adv_report(NULL); + if (!hci_ev) { + return -1; + } + + ev = (void *) hci_ev->data; + report = ev->reports; + + switch (evtype) { + case BLE_HCI_ADV_RPT_EVTYPE_ADV_IND: + report->evt_type = BLE_HCI_LEGACY_ADV_EVTYPE_ADV_IND; + break; + case BLE_HCI_ADV_RPT_EVTYPE_DIR_IND: + report->evt_type = BLE_HCI_LEGACY_ADV_EVTYPE_ADV_DIRECT_IND; + break; + case BLE_HCI_ADV_RPT_EVTYPE_NONCONN_IND: + report->evt_type = BLE_HCI_LEGACY_ADV_EVTYPE_ADV_NONCON_IND; + break; + case BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP: + report->evt_type = BLE_HCI_LEGACY_ADV_EVTYPE_SCAN_RSP_ADV_IND; + break; + case BLE_HCI_ADV_RPT_EVTYPE_SCAN_IND: + report->evt_type = BLE_HCI_LEGACY_ADV_EVTYPE_ADV_SCAN_IND; + break; + default: + BLE_LL_ASSERT(0); + ble_hci_trans_buf_free((uint8_t *) hci_ev); + return -1; + } + + report->addr_type = addr_type; + memcpy(report->addr, addr, BLE_DEV_ADDR_LEN); + report->pri_phy = BLE_PHY_1M; + report->sid = 0xFF; + report->tx_power = 127; + report->rssi = rssi; + + if (inita) { + report->dir_addr_type = inita_type; + memcpy(report->dir_addr, inita, BLE_DEV_ADDR_LEN); + } + + if (adv_data_len) { + hci_ev->length += adv_data_len; + report->data_len = adv_data_len; + os_mbuf_copydata(adv_data, 0, adv_data_len, report->data); + } + + return ble_ll_hci_event_send(hci_ev); +} +#endif + +static int +ble_ll_hci_send_adv_report(uint8_t evtype, + const uint8_t *addr, uint8_t addr_type, int8_t rssi, + uint8_t adv_data_len, struct os_mbuf *adv_data) +{ + struct ble_hci_ev_le_subev_adv_rpt *ev; + struct ble_hci_ev *hci_ev; + int8_t *ev_rssi; + + if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_ADV_RPT)) { + return -1; + } + + /* Drop packet if adv data doesn't fit, note extra 1 is for RSSI */ + if ((sizeof(*ev) + sizeof(ev->reports[0]) + adv_data_len + 1) > BLE_HCI_MAX_DATA_LEN) { + STATS_INC(ble_ll_stats, adv_evt_dropped); + return -1; + } + + hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO); + if (!hci_ev) { + return -1; + } + + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*ev) + sizeof(ev->reports[0]) + adv_data_len + 1; + ev = (void *) hci_ev->data; + + ev->subev_code = BLE_HCI_LE_SUBEV_ADV_RPT; + ev->num_reports = 1; + + ev->reports[0].type = evtype; + ev->reports[0].addr_type = addr_type; + memcpy(ev->reports[0].addr, addr, BLE_DEV_ADDR_LEN); + ev->reports[0].data_len = adv_data_len; + os_mbuf_copydata(adv_data, 0, adv_data_len, ev->reports[0].data); + + /* RSSI is after adv data... */ + ev_rssi = (int8_t *) (hci_ev->data + sizeof(*ev) + sizeof(ev->reports[0]) + adv_data_len); + *ev_rssi = rssi; + + return ble_ll_hci_event_send(hci_ev); +} + +static int +ble_ll_hci_send_dir_adv_report(const uint8_t *addr, uint8_t addr_type, + const uint8_t *inita, uint8_t inita_type, + int8_t rssi) +{ + struct ble_hci_ev_le_subev_direct_adv_rpt *ev; + struct ble_hci_ev *hci_ev; + + if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT)) { + return -1; + } + + hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO); + if (!hci_ev) { + return -1; + } + + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*ev) + sizeof(*(ev->reports)); + ev = (void *) hci_ev->data; + + ev->subev_code = BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT; + ev->num_reports = 1; + + ev->reports[0].type = BLE_HCI_ADV_RPT_EVTYPE_DIR_IND; + ev->reports[0].addr_type = addr_type; + memcpy(ev->reports[0].addr, addr, BLE_DEV_ADDR_LEN); + ev->reports[0].dir_addr_type = inita_type; + memcpy(ev->reports[0].dir_addr, inita, BLE_DEV_ADDR_LEN); + ev->reports[0].rssi = rssi; + + return ble_ll_hci_event_send(hci_ev); +} + +static int +ble_ll_scan_dup_update_legacy(uint8_t addr_type, const uint8_t *addr, + uint8_t subev, uint8_t evtype) +{ + struct ble_ll_scan_dup_entry *e; + uint8_t type; + + type = BLE_LL_SCAN_ENTRY_TYPE_LEGACY(addr_type); + + /* + * We assume ble_ll_scan_dup_check() was called before which either matched + * some entry or allocated new one and placed in on the top of queue. + */ + + e = TAILQ_FIRST(&g_scan_dup_list); + BLE_LL_ASSERT(e && e->type == type && !memcmp(e->addr, addr, 6)); + + if (subev == BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT) { + e->flags |= BLE_LL_SCAN_DUP_F_DIR_ADV_REPORT_SENT; + } else { + if (evtype == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) { + e->flags |= BLE_LL_SCAN_DUP_F_SCAN_RSP_SENT; + } else { + e->flags |= BLE_LL_SCAN_DUP_F_ADV_REPORT_SENT; + } + } + + return 0; +} + +/** + * Send an advertising report to the host. + * + * NOTE: while we are allowed to send multiple devices in one report, we + * will just send for one for now. + * + * @param pdu_type + * @param txadd + * @param rxbuf + * @param hdr + * @param scansm + */ +static void +ble_ll_scan_send_adv_report(uint8_t pdu_type, + const uint8_t *adva, uint8_t adva_type, + const uint8_t *inita, uint8_t inita_type, + struct os_mbuf *om, + struct ble_mbuf_hdr *hdr, + struct ble_ll_scan_sm *scansm) +{ + uint8_t subev = BLE_HCI_LE_SUBEV_ADV_RPT; + uint8_t adv_data_len; + uint8_t evtype; + int rc; + + if (pdu_type == BLE_ADV_PDU_TYPE_ADV_DIRECT_IND) { + if (ble_ll_is_rpa(inita, inita_type)) { + /* For resolvable we send separate subevent */ + subev = BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT; + } + + evtype = BLE_HCI_ADV_RPT_EVTYPE_DIR_IND; + adv_data_len = 0; + } else { + if (pdu_type == BLE_ADV_PDU_TYPE_ADV_IND) { + evtype = BLE_HCI_ADV_RPT_EVTYPE_ADV_IND; + } else if (pdu_type == BLE_ADV_PDU_TYPE_ADV_SCAN_IND) { + evtype = BLE_HCI_ADV_RPT_EVTYPE_SCAN_IND; + } else if (pdu_type == BLE_ADV_PDU_TYPE_ADV_NONCONN_IND) { + evtype = BLE_HCI_ADV_RPT_EVTYPE_NONCONN_IND; + } else { + evtype = BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP; + } + adv_data_len = om->om_data[1] - BLE_DEV_ADDR_LEN; + os_mbuf_adj(om, BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN); + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + /* If RPA has been used, make sure we use correct address types + * in the advertising report. + */ + if (BLE_MBUF_HDR_RESOLVED(hdr)) { + adva_type += 2; + } + if (BLE_MBUF_HDR_TARGETA_RESOLVED(hdr)) { + inita_type += 2; + } +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (scansm->ext_scanning) { + rc = ble_ll_hci_send_legacy_ext_adv_report(evtype, + adva, adva_type, + hdr->rxinfo.rssi, + adv_data_len, om, + inita, inita_type); + goto done; + } +#endif + + if (subev == BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT) { + rc = ble_ll_hci_send_dir_adv_report(adva, adva_type, inita, inita_type, + hdr->rxinfo.rssi); + goto done; + } + + rc = ble_ll_hci_send_adv_report(evtype, adva, adva_type, hdr->rxinfo.rssi, + adv_data_len, om); +done: + if (!rc && scansm->scan_filt_dups) { + ble_ll_scan_dup_update_legacy(adva_type, adva, subev, evtype); + } +} + +static void +ble_ll_get_chan_to_scan(struct ble_ll_scan_sm *scansm, uint8_t *chan, + int *phy) +{ + struct ble_ll_scan_params *scanp = scansm->scanp; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + struct ble_ll_aux_data *aux_data = scansm->cur_aux_data; + + if (!scansm->ext_scanning || !aux_data || !aux_data->scanning) { + *chan = scanp->scan_chan; + *phy = scanp->phy; + return; + } + + *chan = aux_data->chan; + *phy = aux_data->aux_phy; +#else + *chan = scanp->scan_chan; + *phy = scanp->phy; +#endif +} +/** + * Called to enable the receiver for scanning. + * + * Context: Link Layer task + * + * @param sch + * + * @return int + */ +static int +ble_ll_scan_start(struct ble_ll_scan_sm *scansm, struct ble_ll_sched_item *sch) +{ + int rc; + struct ble_ll_scan_params *scanp = scansm->scanp; + uint8_t scan_chan; +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + uint8_t phy_mode; +#endif + int phy; + + BLE_LL_ASSERT(scansm->scan_rsp_pending == 0); + + ble_ll_get_chan_to_scan(scansm, &scan_chan, &phy); + + /* XXX: right now scheduled item is only present if we schedule for aux + * scan just make sanity check that we have proper combination of + * sch and resulting scan_chan + */ + BLE_LL_ASSERT(!sch || scan_chan < BLE_PHY_ADV_CHAN_START); + BLE_LL_ASSERT(sch || scan_chan >= BLE_PHY_ADV_CHAN_START); + + /* Set channel */ + rc = ble_phy_setchan(scan_chan, BLE_ACCESS_ADDR_ADV, BLE_LL_CRCINIT_ADV); + BLE_LL_ASSERT(rc == 0); + + /* + * Set transmit end callback to NULL in case we transmit a scan request. + * There is a callback for the connect request. + */ + ble_phy_set_txend_cb(NULL, NULL); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + ble_phy_encrypt_disable(); +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + if (ble_ll_resolv_enabled()) { + ble_phy_resolv_list_enable(); + } else { + ble_phy_resolv_list_disable(); + } +#endif + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + phy_mode = ble_ll_phy_to_phy_mode(phy, BLE_HCI_LE_PHY_CODED_ANY); + ble_phy_mode_set(phy_mode, phy_mode); +#endif + + /* XXX: probably need to make sure hfxo is running too */ + /* XXX: can make this better; want to just start asap. */ + if (sch) { + rc = ble_phy_rx_set_start_time(sch->start_time + + g_ble_ll_sched_offset_ticks, + sch->remainder); + } else { + rc = ble_phy_rx_set_start_time(os_cputime_get32() + + g_ble_ll_sched_offset_ticks, 0); + } + if (!rc || rc == BLE_PHY_ERR_RX_LATE) { + /* If we are late here, it is still OK because we keep scanning. + * Clear error + */ + rc = 0; + + /* Enable/disable whitelisting */ + if (scanp->scan_filt_policy & 1) { + ble_ll_whitelist_enable(); + } else { + ble_ll_whitelist_disable(); + } + + /* Set link layer state to scanning */ + if (scanp->scan_type == BLE_SCAN_TYPE_INITIATE) { + ble_ll_state_set(BLE_LL_STATE_INITIATING); + } else { + ble_ll_state_set(BLE_LL_STATE_SCANNING); + } + } + + return rc; +} + +static uint8_t +ble_ll_scan_get_next_adv_prim_chan(uint8_t chan) +{ + ++chan; + if (chan == BLE_PHY_NUM_CHANS) { + chan = BLE_PHY_ADV_CHAN_START; + } + + return chan; +} + +static uint32_t +ble_ll_scan_move_window_to(struct ble_ll_scan_params *scanp, uint32_t time) +{ + uint32_t end_time; + + /* + * Move window until given tick is before or inside window and move to next + * channel for each skipped interval. + */ + + end_time = scanp->timing.start_time + scanp->timing.window; + while (CPUTIME_GEQ(time, end_time)) { + scanp->timing.start_time += scanp->timing.interval; + scanp->scan_chan = ble_ll_scan_get_next_adv_prim_chan(scanp->scan_chan); + end_time = scanp->timing.start_time + scanp->timing.window; + } + + return scanp->timing.start_time; +} + +static bool +ble_ll_scan_is_inside_window(struct ble_ll_scan_params *scanp, uint32_t time) +{ + uint32_t start_time; + + /* Make sure we are checking against closest window */ + start_time = ble_ll_scan_move_window_to(scanp, time); + + if (scanp->timing.window == scanp->timing.interval) { + /* always inside window in continuous scan */ + return true; + } + + return CPUTIME_GEQ(time, start_time) && + CPUTIME_LT(time, start_time + scanp->timing.window); +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +static void +ble_ll_scan_aux_data_free(struct ble_ll_aux_data *aux_data) +{ + if (aux_data) { + if (aux_data->evt) { + ble_hci_trans_buf_free((uint8_t *)aux_data->evt); + aux_data->evt = NULL; + } + os_memblock_put(&ext_scan_aux_pool, aux_data); + STATS_INC(ble_ll_stats, aux_freed); + } +} + +struct ble_ll_aux_data * +ble_ll_scan_aux_data_ref(struct ble_ll_aux_data *aux_data) +{ + os_sr_t sr; + + BLE_LL_ASSERT(aux_data); + + OS_ENTER_CRITICAL(sr); + aux_data->ref_cnt++; + ble_ll_trace_u32x2(BLE_LL_TRACE_ID_AUX_REF, (uint32_t) aux_data, aux_data->ref_cnt); + + OS_EXIT_CRITICAL(sr); + + return aux_data; +} + +void +ble_ll_scan_aux_data_unref(struct ble_ll_aux_data *aux_data) +{ + os_sr_t sr; + + BLE_LL_ASSERT(aux_data); + + OS_ENTER_CRITICAL(sr); + aux_data->ref_cnt--; + ble_ll_trace_u32x2(BLE_LL_TRACE_ID_AUX_UNREF, (uint32_t) aux_data, aux_data->ref_cnt); + + if (aux_data->ref_cnt == 0) { + /* + * Some validation to make sure that we completed scan properly: + * - we either did not send any report or sent completed/truncated + * - we only sent one of completed/truncated + * - in case of error, we wither did not send anything or sent truncated + */ + BLE_LL_ASSERT(!(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_ANY) || + ((aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_ANY) && + (aux_data->flags_ll & (BLE_LL_AUX_FLAG_HCI_SENT_COMPLETED | BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED)))); + BLE_LL_ASSERT(!(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_COMPLETED) || !(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED)); + BLE_LL_ASSERT(!(aux_data->flags_ll & BLE_LL_AUX_FLAG_SCAN_ERROR) || + !(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_ANY) || + (aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED)); + + ble_ll_scan_aux_data_free(aux_data); + } + + OS_EXIT_CRITICAL(sr); +} + +static void +ble_ll_scan_sched_remove(struct ble_ll_sched_item *sch) +{ + ble_ll_scan_end_adv_evt(sch->cb_arg); + ble_ll_scan_aux_data_unref(sch->cb_arg); + sch->cb_arg = NULL; +} +#endif +/** + * Stop the scanning state machine + */ +void +ble_ll_scan_sm_stop(int chk_disable) +{ + os_sr_t sr; + uint8_t lls; + struct ble_ll_scan_sm *scansm; + + /* Stop the scanning timer */ + scansm = &g_ble_ll_scan_sm; + os_cputime_timer_stop(&scansm->scan_timer); + + OS_ENTER_CRITICAL(sr); + + /* Disable scanning state machine */ + scansm->scan_enabled = 0; + scansm->restart_timer_needed = 0; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (scansm->ext_scanning) { + ble_ll_scan_clean_cur_aux_data(); + ble_ll_sched_rmv_elem_type(BLE_LL_SCHED_TYPE_AUX_SCAN, ble_ll_scan_sched_remove); + scansm->ext_scanning = 0; + } +#endif + + /* Update backoff if we failed to receive scan response */ + if (scansm->scan_rsp_pending) { + scansm->scan_rsp_pending = 0; + ble_ll_scan_req_backoff(scansm, 0); + } + OS_EXIT_CRITICAL(sr); + + /* Count # of times stopped */ + STATS_INC(ble_ll_stats, scan_stops); + + /* Only set state if we are currently in a scan window */ + if (chk_disable) { + OS_ENTER_CRITICAL(sr); + lls = ble_ll_state_get(); + + if ((lls == BLE_LL_STATE_SCANNING) || + (lls == BLE_LL_STATE_INITIATING && chk_disable == 1)) { + /* Disable phy */ + ble_phy_disable(); + + /* Set LL state to standby */ + ble_ll_state_set(BLE_LL_STATE_STANDBY); + } + OS_EXIT_CRITICAL(sr); + } + + /* No need for RF anymore */ + OS_ENTER_CRITICAL(sr); + ble_ll_rfmgmt_scan_changed(false, 0); + ble_ll_rfmgmt_release(); + OS_EXIT_CRITICAL(sr); +} + +static int +ble_ll_scan_sm_start(struct ble_ll_scan_sm *scansm) +{ + struct ble_ll_scan_params *scanp; + struct ble_ll_scan_params *scanp_next; + + if (!ble_ll_is_valid_own_addr_type(scansm->own_addr_type, g_random_addr)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + BLE_LL_ASSERT(scansm->scanp); + scanp = scansm->scanp; + scanp_next = scansm->scanp_next; + + /* Count # of times started */ + STATS_INC(ble_ll_stats, scan_starts); + + /* Set flag telling us that scanning is enabled */ + scansm->scan_enabled = 1; + + /* Set first advertising channel */ + scanp->scan_chan = BLE_PHY_ADV_CHAN_START; + if (scanp_next) { + scanp_next->scan_chan = BLE_PHY_ADV_CHAN_START; + } + + /* Reset scan request backoff parameters to default */ + scansm->upper_limit = 1; + scansm->backoff_count = 1; + scansm->scan_rsp_pending = 0; + + /* Forget filtered advertisers from previous scan. */ + g_ble_ll_scan_num_rsp_advs = 0; + + os_mempool_clear(&g_scan_dup_pool); + TAILQ_INIT(&g_scan_dup_list); + + /* + * First scan window can start when RF is enabled. Add 1 tick since we are + * most likely not aligned with ticks so RF may be effectively enabled 1 + * tick later. + */ + scanp->timing.start_time = ble_ll_rfmgmt_enable_now(); + ble_ll_rfmgmt_scan_changed(true, scanp->timing.start_time); + + if (scanp_next) { + /* Schedule start time right after first phy */ + scanp_next->timing.start_time = scanp->timing.start_time + + scanp->timing.window; + } + + /* Start scan at 1st window */ + os_cputime_timer_start(&scansm->scan_timer, scanp->timing.start_time); + + return BLE_ERR_SUCCESS; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +static void +ble_ll_aux_scan_rsp_failed(struct ble_ll_scan_sm *scansm) +{ + if (!scansm->cur_aux_data) { + return; + } + + STATS_INC(ble_ll_stats, aux_scan_rsp_err); + ble_ll_scan_interrupted(scansm); +} +#endif + +static void +ble_ll_scan_interrupted_event_cb(struct ble_npl_event *ev) +{ + struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + struct ble_ll_aux_data *aux_data; +#endif + + if (!scansm->scan_enabled) { + return; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + aux_data = ble_npl_event_get_arg(ev); + + if (aux_data) { + if (scansm->scan_rsp_pending) { + STATS_INC(ble_ll_stats, aux_scan_rsp_err); + } + ble_ll_scan_end_adv_evt(aux_data); + ble_ll_scan_aux_data_unref(aux_data); + ble_npl_event_set_arg(ev, NULL); + STATS_INC(ble_ll_stats, aux_missed_adv); + } +#endif + + /* + * If we timed out waiting for a response, the scan response pending + * flag should be set. Deal with scan backoff. Put device back into rx. + */ + + if (scansm->scan_rsp_pending) { + scansm->scan_rsp_pending = 0; + ble_ll_scan_req_backoff(scansm, 0); + } + + ble_ll_scan_chk_resume(); +} + +/** + * Called to process the scanning OS event which was posted to the LL task + * + * Context: Link Layer task. + * + * @param arg + */ +static void +ble_ll_scan_event_proc(struct ble_npl_event *ev) +{ + struct ble_ll_scan_sm *scansm; + os_sr_t sr; + bool start_scan; + bool inside_window; + struct ble_ll_scan_params *scanp; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + bool inside_window_next; + struct ble_ll_scan_params *scanp_next; +#endif + uint32_t next_proc_time; + uint32_t now; + /* + * Get the scanning state machine. If not enabled (this is possible), just + * leave and do nothing (just make sure timer is stopped). + */ + scansm = (struct ble_ll_scan_sm *)ble_npl_event_get_arg(ev); + scanp = scansm->scanp; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + scanp_next = scansm->scanp_next; +#endif + + OS_ENTER_CRITICAL(sr); + if (!scansm->scan_enabled) { + os_cputime_timer_stop(&scansm->scan_timer); + ble_ll_rfmgmt_scan_changed(false, 0); + ble_ll_rfmgmt_release(); + OS_EXIT_CRITICAL(sr); + return; + } + + if (scansm->cur_aux_data || scansm->scan_rsp_pending) { + /* Aux scan in progress. Wait */ + STATS_INC(ble_ll_stats, scan_timer_stopped); + scansm->restart_timer_needed = 1; + OS_EXIT_CRITICAL(sr); + return; + } + + now = os_cputime_get32(); + + inside_window = ble_ll_scan_is_inside_window(scanp, now); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + /* Update also next PHY if configured */ + if (scanp_next) { + inside_window_next = ble_ll_scan_is_inside_window(scanp_next, now); + + /* + * Switch PHY if current PHY is outside window and next PHY is either + * inside window or has next window earlier than current PHY. + */ + if (!inside_window && + ((inside_window_next || CPUTIME_LEQ(scanp_next->timing.start_time, + scanp->timing.start_time)))) { + scansm->scanp = scanp_next; + scansm->scanp_next = scanp; + scanp = scansm->scanp; + scanp_next = scansm->scanp_next; + inside_window = inside_window_next; + } + } +#endif + + /* + * At this point scanp and scanp_next point to current or closest scan + * window on both PHYs (scanp is the closer one). Make sure RF is enabled + * on time. + */ + ble_ll_rfmgmt_scan_changed(true, scanp->timing.start_time); + + /* + * If we are inside window, next scan proc should happen at the end of + * current window to either disable scan or switch to next PHY. + * If we are outside window, next scan proc should happen at the time of + * closest scan window. + */ + if (inside_window) { + next_proc_time = scanp->timing.start_time + scanp->timing.window; + } else { + next_proc_time = scanp->timing.start_time; + } + + /* + * If we are not in the standby state it means that the scheduled + * scanning event was overlapped in the schedule. In this case all we do + * is post the scan schedule end event. + */ + start_scan = inside_window; + switch (ble_ll_state_get()) { + case BLE_LL_STATE_ADV: + case BLE_LL_STATE_CONNECTION: + case BLE_LL_STATE_SYNC: + start_scan = false; + break; + case BLE_LL_STATE_INITIATING: + /* Must disable PHY since we will move to a new channel */ + ble_phy_disable(); + if (!inside_window) { + ble_ll_state_set(BLE_LL_STATE_STANDBY); + } + /* PHY is disabled - make sure we do not wait for AUX_CONNECT_RSP */ + ble_ll_conn_reset_pending_aux_conn_rsp(); + break; + case BLE_LL_STATE_SCANNING: + /* Must disable PHY since we will move to a new channel */ + ble_phy_disable(); + if (!inside_window) { + ble_ll_state_set(BLE_LL_STATE_STANDBY); + } + break; + case BLE_LL_STATE_STANDBY: + break; + default: + BLE_LL_ASSERT(0); + break; + } + + if (start_scan) { + ble_ll_scan_start(scansm, NULL); + } else { + ble_ll_rfmgmt_release(); + } + + OS_EXIT_CRITICAL(sr); + os_cputime_timer_start(&scansm->scan_timer, next_proc_time); +} + +/** + * ble ll scan rx pdu start + * + * Called when a PDU reception has started and the Link Layer is in the + * scanning state. + * + * Context: Interrupt + * + * @param pdu_type + * @param rxflags + * + * @return int + * 0: we will not attempt to reply to this frame + * 1: we may send a response to this frame. + */ +int +ble_ll_scan_rx_isr_start(uint8_t pdu_type, uint16_t *rxflags) +{ + int rc; + struct ble_ll_scan_sm *scansm; + struct ble_ll_scan_params *scanp; + + rc = 0; + scansm = &g_ble_ll_scan_sm; + scanp = scansm->scanp; + + switch (scanp->scan_type) { + case BLE_SCAN_TYPE_ACTIVE: + /* If adv ind or scan ind, we may send scan request */ + if ((pdu_type == BLE_ADV_PDU_TYPE_ADV_IND) || + (pdu_type == BLE_ADV_PDU_TYPE_ADV_SCAN_IND)) { + rc = 1; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if ((pdu_type == BLE_ADV_PDU_TYPE_ADV_EXT_IND && scansm->ext_scanning)) { + *rxflags |= BLE_MBUF_HDR_F_EXT_ADV; + rc = 1; + } +#endif + + if (scansm->cur_aux_data && !scansm->scan_rsp_pending ) { + STATS_INC(ble_ll_stats, aux_received); + } + + /* + * If this is the first PDU after we sent the scan response (as + * denoted by the scan rsp pending flag), we set a bit in the ble + * header so the link layer can check to see if the scan request + * was successful. We do it this way to let the Link Layer do the + * work for successful scan requests. If failed, we do the work here. + */ + if (scansm->scan_rsp_pending) { + scansm->scan_rsp_pending = 0; + + if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_RSP) { + *rxflags |= BLE_MBUF_HDR_F_SCAN_RSP_RXD; + } else if (pdu_type == BLE_ADV_PDU_TYPE_AUX_SCAN_RSP) { + *rxflags |= BLE_MBUF_HDR_F_SCAN_RSP_RXD; + } else { + ble_ll_scan_req_backoff(scansm, 0); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + ble_ll_aux_scan_rsp_failed(scansm); +#endif + } + } + break; + case BLE_SCAN_TYPE_PASSIVE: +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if ((pdu_type == BLE_ADV_PDU_TYPE_ADV_EXT_IND && scansm->ext_scanning)) { + *rxflags |= BLE_MBUF_HDR_F_EXT_ADV; + } + break; +#endif + default: + break; + } + + return rc; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +static uint8_t +ble_ll_ext_adv_phy_mode_to_local_phy(uint8_t adv_phy_mode) +{ + switch (adv_phy_mode) { + case 0x00: + return BLE_PHY_1M; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) + case 0x01: + return BLE_PHY_2M; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + case 0x02: + return BLE_PHY_CODED; +#endif + } + + return 0; +} + +static int +ble_ll_ext_scan_parse_aux_ptr(struct ble_ll_aux_data *aux_data, uint8_t *buf) +{ + uint32_t aux_ptr_field = get_le32(buf) & 0x00FFFFFF; + + aux_data->chan = (aux_ptr_field) & 0x3F; + if (aux_data->chan >= BLE_PHY_NUM_DATA_CHANS) { + return -1; + } + + /* TODO use CA aux_ptr_field >> 6 */ + + aux_data->offset = 30 * ((aux_ptr_field >> 8) & 0x1FFF); + + if ((aux_ptr_field >> 7) & 0x01) { + aux_data->offset *= 10; + aux_data->offset_units = 1; + } + + if (aux_data->offset < BLE_LL_MAFS) { + return -1; + } + + aux_data->aux_phy = + ble_ll_ext_adv_phy_mode_to_local_phy((aux_ptr_field >> 21) & 0x07); + if (aux_data->aux_phy == 0) { + return -1; + } + + return 0; +} + +static void +ble_ll_ext_scan_parse_adv_info(struct ext_adv_report *report, const uint8_t *buf) +{ + uint16_t adv_info = get_le16(buf); + + /* TODO Use DID */ + + report->sid = (adv_info >> 12); +} + +/** + * ble_ll_scan_update_aux_data + * + * Update aux_data stored in ble_hdr.rxinfo.user_data. If no aux_data is present + * (i.e. processing ADV_EXT_IND) this will try to allocate new aux_data. + * + * Context: Interrupt + * + * @param ble_hdr + * @param rxbuf + * + * @return int + * 1: do not scan for next AUX (no AuxPtr or malformed data) + * 0: scan for next AUX (valid AuxPtr found) + * -1: error + */ +int +ble_ll_scan_update_aux_data(struct ble_mbuf_hdr *ble_hdr, uint8_t *rxbuf, + bool *adva_present) +{ + uint8_t pdu_hdr; + uint8_t pdu_len; + uint8_t adv_mode; + uint8_t eh_len; + uint8_t eh_flags; + uint8_t *eh; + struct ble_ll_aux_data *aux_data; + bool is_aux; + + aux_data = ble_hdr->rxinfo.user_data; + /* aux_data is initially not set only for ADV_EXT_IND */ + is_aux = aux_data; + + pdu_hdr = rxbuf[0]; + pdu_len = rxbuf[1]; + + /* PDU without at least Extended Header Length is invalid */ + if (pdu_len == 0) { + return -1; + } + + adv_mode = rxbuf[2] >> 6; + eh_len = rxbuf[2] & 0x3f; + eh_flags = rxbuf[3]; + eh = &rxbuf[4]; + + /* + * PDU without Extended Header is valid in case of last AUX_CHAIN_IND in + * chain so aux_data has to be set and advertising mode has to be 00b, + * otherwise it's an invalid PDU. + */ + if (eh_len == 0) { + if (!aux_data || adv_mode) { + return -1; + } + aux_data->flags_isr |= BLE_LL_AUX_FLAG_SCAN_COMPLETE; + return 1; + } + + /* + * If aux_data is not set, this is ADV_EXT_IND which starts new extended + * advertising event. + */ + if (!aux_data) { + if (ble_ll_scan_ext_adv_init(&aux_data)) { + return -1; + } + + aux_data->aux_primary_phy = ble_hdr->rxinfo.phy; + } else { + if (aux_data->flags_isr & BLE_LL_AUX_FLAG_AUX_ADV_RECEIVED) { + aux_data->flags_isr |= BLE_LL_AUX_FLAG_AUX_CHAIN_RECEIVED; + } else { + aux_data->flags_isr |= BLE_LL_AUX_FLAG_AUX_ADV_RECEIVED; + } + } + + /* Now parse extended header... */ + + if (eh_flags & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) { + aux_data->flags |= BLE_LL_AUX_HAS_ADVA; + memcpy(aux_data->adva, eh, 6); + aux_data->adva_type = !!(pdu_hdr & BLE_ADV_PDU_HDR_TXADD_MASK); + eh += BLE_LL_EXT_ADV_ADVA_SIZE; + + if (adva_present) { + *adva_present = true; + } + } else if (adva_present) { + *adva_present = false; + } + + if (eh_flags & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) { + aux_data->flags |= BLE_LL_AUX_HAS_TARGETA; + memcpy(aux_data->targeta, eh, 6); + aux_data->targeta_type = !!(pdu_hdr & BLE_ADV_PDU_HDR_RXADD_MASK); + eh += BLE_LL_EXT_ADV_TARGETA_SIZE; + } + + + if (eh_flags & (1 << BLE_LL_EXT_ADV_CTE_INFO_BIT)) { + eh += 1; + } + + if (eh_flags & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) { + aux_data->flags |= BLE_LL_AUX_HAS_ADI; + if (is_aux) { + if (get_le16(eh) != aux_data->adi) { + aux_data->flags_isr |= BLE_LL_AUX_FLAG_SCAN_ERROR; + STATS_INC(ble_ll_stats, aux_chain_err); + } + } else { + aux_data->adi = get_le16(eh); + } + eh += BLE_LL_EXT_ADV_DATA_INFO_SIZE; + } + + if (eh_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) { + if (ble_ll_ext_scan_parse_aux_ptr(aux_data, eh)) { + aux_data->flags_isr |= BLE_LL_AUX_FLAG_SCAN_ERROR; + } + } else if (!(adv_mode & BLE_LL_EXT_ADV_MODE_SCAN)) { + /* No AuxPtr for scannable PDU is ignored since we can still scan it */ + aux_data->flags_isr |= BLE_LL_AUX_FLAG_SCAN_COMPLETE; + } + + ble_hdr->rxinfo.user_data = aux_data; + + /* Do not scan for next AUX if either no AuxPtr or malformed data found */ + return !(eh_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) || + (aux_data->flags_isr & BLE_LL_AUX_FLAG_SCAN_ERROR); +} + +/** + * Called when a receive ADV_EXT PDU has ended. + * + * Context: Interrupt + * + * @return int + * < 0 Error + * >= 0: Success (number of bytes left in PDU) + * + */ +static int +ble_ll_scan_parse_ext_hdr(struct os_mbuf *om, + const uint8_t *adva, uint8_t adva_type, + const uint8_t *inita, uint8_t inita_type, + struct ble_mbuf_hdr *ble_hdr, + struct ext_adv_report *report) +{ + uint8_t pdu_len; + uint8_t ext_hdr_len; + uint8_t ext_hdr_flags; + uint8_t *ext_hdr; + uint8_t *rxbuf = om->om_data; + int i = 1; + struct ble_ll_scan_sm *scansm; + struct ble_ll_aux_data *aux_data = ble_hdr->rxinfo.user_data; + + BLE_LL_ASSERT(report); + + scansm = &g_ble_ll_scan_sm; + + if (!scansm->ext_scanning) { + /* Ignore ext adv if host does not want it*/ + return -1; + } + + pdu_len = rxbuf[1]; + if (pdu_len == 0) { + return -1; + } + + report->evt_type = rxbuf[2] >> 6; + if ( report->evt_type > BLE_LL_EXT_ADV_MODE_SCAN) { + return -1; + } + + if (BLE_MBUF_HDR_SCAN_RSP_RXD(ble_hdr)) { + report->evt_type |= BLE_HCI_ADV_SCAN_RSP_MASK; + } + + ext_hdr_len = rxbuf[2] & 0x3F; + os_mbuf_adj(om, 3); + + ext_hdr_flags = rxbuf[3]; + ext_hdr = &rxbuf[4]; + + if (ext_hdr_len) { + i = 0; + if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) { + i += BLE_LL_EXT_ADV_ADVA_SIZE; + } + + if (adva) { + memcpy(report->addr, adva, 6); + report->addr_type = adva_type; + } + + if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) { + i += BLE_LL_EXT_ADV_TARGETA_SIZE; + } + + if (inita) { + memcpy(report->dir_addr, inita, 6); + report->dir_addr_type = inita_type; + report->evt_type |= BLE_HCI_ADV_DIRECT_MASK; + } + + if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_CTE_INFO_BIT)) { + /* Just skip it for now*/ + i += 1; + } + + if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) { + ble_ll_ext_scan_parse_adv_info(report, (ext_hdr + i)); + i += BLE_LL_EXT_ADV_DATA_INFO_SIZE; + } else if (report->evt_type & BLE_HCI_ADV_SCAN_RSP_MASK) { + report->sid = (aux_data->adi >> 12); + } + + /* In this point of time we don't want to care about aux ptr */ + if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) { + i += BLE_LL_EXT_ADV_AUX_PTR_SIZE; + } + + if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_SYNC_INFO_BIT)) { + report->periodic_itvl = get_le16(ext_hdr + i + 2); + i += BLE_LL_EXT_ADV_SYNC_INFO_SIZE; + } + + if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_TX_POWER_BIT)) { + report->tx_power = *(ext_hdr + i); + i += BLE_LL_EXT_ADV_TX_POWER_SIZE; + } + + /* TODO Handle ACAD if needed */ + } + + /* In the event we need information on primary and secondary PHY used during + * advertising. + */ + if (!aux_data) { + report->pri_phy = ble_hdr->rxinfo.phy; + goto done; + } + + report->sec_phy = aux_data->aux_phy; + report->pri_phy = aux_data->aux_primary_phy; + + if (ext_hdr_len) { + /* Adjust mbuf to contain advertising data only */ + os_mbuf_adj(om, ext_hdr_len); + } + + /* Let us first keep update event type in aux data. + * Note that in aux chain and aux scan response packets + * we do miss original event type, which we need for advertising report. + */ + aux_data->evt_type |= report->evt_type; + report->evt_type = aux_data->evt_type; + +done: + return pdu_len - ext_hdr_len - 1; +} + +static int +ble_ll_scan_get_addr_from_ext_adv(uint8_t *rxbuf, struct ble_mbuf_hdr *ble_hdr, + uint8_t **addr, uint8_t *addr_type, + uint8_t **inita, uint8_t *inita_type, + int *ext_mode) +{ + uint8_t pdu_len; + uint8_t ext_hdr_len; + uint8_t ext_hdr_flags; + uint8_t *ext_hdr; + bool has_adva = false; + bool has_inita = false; + int i; + struct ble_ll_aux_data *aux_data = ble_hdr->rxinfo.user_data; + + *addr = NULL; + *inita = NULL; + + pdu_len = rxbuf[1]; + if (pdu_len == 0) { + return -1; + } + + *ext_mode = rxbuf[2] >> 6; + if (*ext_mode > BLE_LL_EXT_ADV_MODE_SCAN) { + return -1; + } + + ext_hdr_len = rxbuf[2] & 0x3F; + if (ext_hdr_len == 0) { + goto done; + } + + ext_hdr_flags = rxbuf[3]; + ext_hdr = &rxbuf[4]; + + i = 0; + if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) { + if (ext_hdr_len < BLE_LL_EXT_ADV_ADVA_SIZE) { + return -1; + } + + *addr = ext_hdr + i; + *addr_type = + ble_ll_get_addr_type(rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK); + i += BLE_LL_EXT_ADV_ADVA_SIZE; + + has_adva = true; + } + + if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) { + *inita = ext_hdr + i; + *inita_type = + ble_ll_get_addr_type(rxbuf[0] & BLE_ADV_PDU_HDR_RXADD_MASK); + i += BLE_LL_EXT_ADV_TARGETA_SIZE; + + has_inita = true; + } + +done: + /* Check if we had address already. If yes, replace it with new one */ + + if (aux_data) { + /* If address has been provided, we do have it already in aux_data.*/ + if (aux_data->flags & BLE_LL_AUX_HAS_ADVA) { + if (!has_adva) { + *addr = aux_data->adva; + *addr_type = aux_data->adva_type; + } else { + memcpy(aux_data->adva, *addr, 6); + aux_data->adva_type = *addr_type; + } + } + + if (aux_data->flags & BLE_LL_AUX_HAS_TARGETA) { + if (!has_inita) { + *inita = aux_data->targeta; + *inita_type = aux_data->targeta_type; + } else { + memcpy(aux_data->targeta, *inita, 6); + aux_data->targeta_type = *inita_type; + } + } + } + + return 0; +} +#endif + +int +ble_ll_scan_adv_decode_addr(uint8_t pdu_type, uint8_t *rxbuf, + struct ble_mbuf_hdr *ble_hdr, + uint8_t **addr, uint8_t *addr_type, + uint8_t **inita, uint8_t *inita_type, + int *ext_mode) +{ + /* + * XXX this should be only used for legacy advertising, but need to refactor + * code in ble_ll_init first so it does not call this for ext + */ + + if (pdu_type != BLE_ADV_PDU_TYPE_ADV_EXT_IND && + pdu_type != BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP) { + /* Legacy advertising */ + *addr_type = ble_ll_get_addr_type(rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK); + *addr = rxbuf + BLE_LL_PDU_HDR_LEN; + + if (pdu_type != BLE_ADV_PDU_TYPE_ADV_DIRECT_IND) { + *inita = NULL; + *inita_type = 0; + return 0; + } + + *inita = rxbuf + BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN; + *inita_type = ble_ll_get_addr_type(rxbuf[0] & BLE_ADV_PDU_HDR_RXADD_MASK); + + return 0; + } + + /* Extended advertising */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + return ble_ll_scan_get_addr_from_ext_adv(rxbuf, ble_hdr, addr, addr_type, + inita, inita_type, ext_mode); +#else + return -1; +#endif + + return 0; +} + +static void +ble_ll_scan_get_addr_data_from_legacy(uint8_t pdu_type, uint8_t *rxbuf, + struct ble_ll_scan_addr_data *addrd) +{ + BLE_LL_ASSERT(pdu_type < BLE_ADV_PDU_TYPE_ADV_EXT_IND); + + addrd->adva_present = true; + + addrd->adva = rxbuf + BLE_LL_PDU_HDR_LEN; + addrd->adva_type = ble_ll_get_addr_type(rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK); + + if (pdu_type == BLE_ADV_PDU_TYPE_ADV_DIRECT_IND) { + addrd->targeta = rxbuf + BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN; + addrd->targeta_type = ble_ll_get_addr_type(rxbuf[0] & BLE_ADV_PDU_HDR_RXADD_MASK); + } else { + addrd->targeta = NULL; + addrd->targeta_type = 0; + } +} + +/* + * Matches incoming PDU using scan filter policy and whitelist, if applicable. + * This will also resolve addresses and update flags/fields in header and + * addr_data as needed. + * + * @return 0 = no match + * 1 = match + * 2 = match, but do not scan + */ +static int +ble_ll_scan_rx_filter(struct ble_mbuf_hdr *hdr, struct ble_ll_scan_addr_data *addrd) +{ + struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; + struct ble_ll_scan_params *scanp = scansm->scanp; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + struct ble_ll_aux_data *aux_data = hdr->rxinfo.user_data; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; + struct ble_ll_resolv_entry *rl = NULL; +#endif + bool scan_req_allowed = true; + int resolved = 0; + + /* Use AdvA as initial advertiser address, we may try to resolve it later */ + addrd->adv_addr = addrd->adva; + addrd->adv_addr_type = addrd->adva_type; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + /* By default, assume AdvA is not resolved */ + rxinfo->rpa_index = -1; + + switch (ble_ll_addr_subtype(addrd->adva, addrd->adva_type)) { + case BLE_LL_ADDR_SUBTYPE_RPA: + /* + * Only resolve if packet actually contained AdvA. + * In extended advertising PDUs we may use RL index from a PDU that + * already had AdvA (e.g. ADV_EXT_IND in case of AUX_ADV_IND without + * AdvA). In legacy advertising PDUs we always need to resolve AdvA. + */ + if (addrd->adva_present) { + rxinfo->rpa_index = ble_hw_resolv_list_match(); + } else { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + BLE_LL_ASSERT(aux_data); + rxinfo->rpa_index = aux_data->rpa_index; +#else + BLE_LL_ASSERT(false); + rxinfo->rpa_index = -1; +#endif + } + + if (rxinfo->rpa_index < 0) { + break; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (aux_data) { + aux_data->rpa_index = rxinfo->rpa_index; + } +#endif + + /* Use resolved identity address as advertiser address */ + rl = &g_ble_ll_resolv_list[rxinfo->rpa_index]; + addrd->adv_addr = rl->rl_identity_addr; + addrd->adv_addr_type = rl->rl_addr_type; + addrd->rl = rl; + + rxinfo->flags |= BLE_MBUF_HDR_F_RESOLVED; + resolved = 1; + break; + case BLE_LL_ADDR_SUBTYPE_IDENTITY: + /* + * If AdvA is an identity address, we need to check if that device was + * added to RL in order to use proper privacy mode. + */ + rl = ble_ll_resolv_list_find(addrd->adva, addrd->adva_type); + if (!rl) { + break; + } + + addrd->rl = rl; + + /* Ignore device if using network privacy mode and it has IRK */ + if ((rl->rl_priv_mode == BLE_HCI_PRIVACY_NETWORK) && rl->rl_has_peer) { + return 0; + } + break; + default: + /* NRPA goes through filtering policy directly */ + break; + } + + if (addrd->targeta) { + switch (ble_ll_addr_subtype(addrd->targeta, addrd->targeta_type)) { + case BLE_LL_ADDR_SUBTYPE_RPA: + /* Check if TargetA can be resolved using the same RL entry as AdvA */ + if (rl && ble_ll_resolv_rpa(addrd->targeta, rl->rl_local_irk)) { + rxinfo->flags |= BLE_MBUF_HDR_F_TARGETA_RESOLVED; + break; + } + + /* Check if scan filter policy allows unresolved RPAs to be processed */ + if (!(scanp->scan_filt_policy & 0x02)) { + return 0; + } + + /* + * We will notify host as requited by scan policy, but make sure we + * do not send scan request since we do not know if this is directed + * to us. + */ + scan_req_allowed = false; + break; + case BLE_LL_ADDR_SUBTYPE_IDENTITY: + /* We shall ignore identity in TargetA if we are using RPA */ + if ((scanp->own_addr_type & 0x02) && rl && rl->rl_has_local) { + return 0; + } + /* Ignore if not directed to us */ + if (!ble_ll_is_our_devaddr(addrd->targeta, addrd->targeta_type)) { + return 0; + } + break; + default: + /* NRPA goes through filtering policy directly */ + break; + } + } +#else + /* Ignore if not directed to us */ + if (addrd->targeta && + !ble_ll_is_our_devaddr(addrd->targeta, addrd->targeta_type)) { + return 0; + } +#endif + + /* Check on WL if required by scan filter policy */ + if (scanp->scan_filt_policy & 0x01) { + if (!ble_ll_whitelist_match(addrd->adv_addr, addrd->adv_addr_type, resolved)) { + return 0; + } + } + + return scan_req_allowed ? 1 : 2; +} + +static int +ble_ll_scan_rx_isr_on_legacy(uint8_t pdu_type, uint8_t *rxbuf, + struct ble_mbuf_hdr *hdr, + struct ble_ll_scan_addr_data *addrd) +{ + struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; + struct ble_ll_scan_params *scanp = scansm->scanp; + struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; + uint8_t sreq_adva_type; + uint8_t *sreq_adva; + int rc; + + ble_ll_scan_get_addr_data_from_legacy(pdu_type, rxbuf, addrd); + + if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_RSP) { + if (!BLE_MBUF_HDR_SCAN_RSP_RXD(hdr)) { + /* + * We were not expecting scan response so just ignore and do not + * update backoff. + */ + return -1; + } + + sreq_adva_type = !!(scansm->pdu_data.hdr_byte & BLE_ADV_PDU_HDR_RXADD_MASK); + sreq_adva = scansm->pdu_data.adva; + + /* + * Ignore scan response if AdvA does not match AdvA in request and also + * update backoff as if there was no scan response. + */ + if ((addrd->adva_type != sreq_adva_type) || + memcmp(addrd->adva, sreq_adva, BLE_DEV_ADDR_LEN)) { + ble_ll_scan_req_backoff(scansm, 0); + return -1; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + /* + * We are not pushing this one through filters so need to update + * rpa_index here as otherwise pkt_in won't be able to determine + * advertiser address properly. + */ + rxinfo->rpa_index = ble_hw_resolv_list_match(); + if (rxinfo->rpa_index >= 0) { + rxinfo->flags |= BLE_MBUF_HDR_F_RESOLVED; + } +#endif + + rxinfo->flags |= BLE_MBUF_HDR_F_DEVMATCH; + + return 0; + } + + rc = ble_ll_scan_rx_filter(hdr, addrd); + if (!rc) { + return 0; + } + + rxinfo->flags |= BLE_MBUF_HDR_F_DEVMATCH; + + if (rc == 2) { + /* Scan request forbidden by filter policy */ + return 0; + } + + return (scanp->scan_type == BLE_SCAN_TYPE_ACTIVE) && + ((pdu_type == BLE_ADV_PDU_TYPE_ADV_IND) || + (pdu_type == BLE_ADV_PDU_TYPE_ADV_SCAN_IND)); +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +static int +ble_ll_scan_rx_isr_on_aux(uint8_t pdu_type, uint8_t *rxbuf, + struct ble_mbuf_hdr *hdr, + struct ble_ll_scan_addr_data *addrd) +{ + struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; + struct ble_ll_scan_params *scanp = scansm->scanp; + struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; + struct ble_ll_aux_data *aux_data; + int rc; + + if (!scansm->ext_scanning) { + return -1; + } + + rc = ble_ll_scan_update_aux_data(hdr, rxbuf, &addrd->adva_present); + if (rc < 0) { + rxinfo->flags |= BLE_MBUF_HDR_F_AUX_INVALID; + return -1; + } else if (rc == 0) { + rxinfo->flags |= BLE_MBUF_HDR_F_AUX_PTR_WAIT; + } + + /* Now we can update aux_data from header since it may have just been created */ + aux_data = rxinfo->user_data; + + /* + * Restore proper header flags if filtering was already done successfully on + * some previous PDU in an event. + */ + if (aux_data->flags & BLE_LL_AUX_IS_MATCHED) { + rxinfo->flags |= BLE_MBUF_HDR_F_DEVMATCH; + rxinfo->rpa_index = aux_data->rpa_index; + if (rxinfo->rpa_index >= 0) { + rxinfo->flags |= BLE_MBUF_HDR_F_RESOLVED; + } + if (aux_data->flags & BLE_LL_AUX_IS_TARGETA_RESOLVED) { + rxinfo->flags |= BLE_MBUF_HDR_F_TARGETA_RESOLVED; + } + goto done; + } + + if (aux_data->flags & BLE_LL_AUX_HAS_ADVA) { + addrd->adva = aux_data->adva; + addrd->adva_type = aux_data->adva_type; + } else { + /* Accept this PDU and wait for AdvA in aux */ + rxinfo->flags |= BLE_MBUF_HDR_F_DEVMATCH; + return 0; + } + if (aux_data->flags & BLE_LL_AUX_HAS_TARGETA) { + addrd->targeta = aux_data->targeta; + addrd->targeta_type = aux_data->targeta_type; + } else { + addrd->targeta = NULL; + } + + rc = ble_ll_scan_rx_filter(hdr, addrd); + if (!rc) { + return 0; + } + + rxinfo->flags |= BLE_MBUF_HDR_F_DEVMATCH; + + /* + * Once we matched device, there's no need to go through filtering on every + * other PDU in an event so just store info required to restore state for + * subsequent PDUs in aux_data. + */ + aux_data->flags |= BLE_LL_AUX_IS_MATCHED; + if (rxinfo->flags & BLE_MBUF_HDR_F_TARGETA_RESOLVED) { + aux_data->flags |= BLE_LL_AUX_IS_TARGETA_RESOLVED; + /* AdvA state is already stored in rpa_index */ + } + + if (rc == 2) { + /* Scan request forbidden by filter policy */ + return 0; + } + +done: + return (scanp->scan_type == BLE_SCAN_TYPE_ACTIVE) && + ((rxbuf[2] >> 6) == BLE_LL_EXT_ADV_MODE_SCAN); +} +#endif + +static bool +ble_ll_scan_send_scan_req(uint8_t pdu_type, uint8_t *rxbuf, + struct ble_mbuf_hdr *hdr, + struct ble_ll_scan_addr_data *addrd) +{ + struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; + struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + struct ble_ll_aux_data *aux_data = rxinfo->user_data; + uint8_t phy_mode; +#endif + bool is_ext_adv = false; + uint16_t adi = 0; + int rc; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (pdu_type == BLE_ADV_PDU_TYPE_ADV_EXT_IND) { + if (ble_ll_scan_get_adi(aux_data, &adi) < 0) { + return false; + } + is_ext_adv = true; + } +#endif + + /* Check if we already scanned this device successfully */ + if (ble_ll_scan_have_rxd_scan_rsp(addrd->adv_addr, addrd->adv_addr_type, + is_ext_adv, adi)) { + return false; + } + + /* Better not be a scan response pending */ + BLE_LL_ASSERT(scansm->scan_rsp_pending == 0); + + /* We want to send a request. See if backoff allows us */ + if (scansm->backoff_count > 0) { + if (--scansm->backoff_count != 0) { + return false; + } + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + phy_mode = ble_ll_phy_to_phy_mode(rxinfo->phy, BLE_HCI_LE_PHY_CODED_ANY); + if (ble_ll_sched_scan_req_over_aux_ptr(rxinfo->channel, phy_mode)) { + return false; + } +#endif + + /* Use original AdvA in scan request (Core 5.1, Vol 6, Part B, section 6.3) */ + ble_ll_scan_req_pdu_prepare(scansm, addrd->adva, addrd->adva_type, addrd->rl); + + rc = ble_phy_tx(ble_ll_scan_req_tx_pdu_cb, scansm, BLE_PHY_TRANSITION_TX_RX); + if (rc) { + return false; + } + + scansm->scan_rsp_pending = 1; + rxinfo->flags |= BLE_MBUF_HDR_F_SCAN_REQ_TXD; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (rxinfo->channel < BLE_PHY_NUM_DATA_CHANS) { + /* Keep aux_data for expected scan response */ + scansm->cur_aux_data = ble_ll_scan_aux_data_ref(aux_data); + STATS_INC(ble_ll_stats, aux_scan_req_tx); + } +#endif + + return true; +} + +/** + * Called when a receive PDU has ended. + * + * Context: Interrupt + * + * @param rxpdu + * + * @return int + * < 0: Disable the phy after reception. + * == 0: Success. Do not disable the PHY. + * > 0: Do not disable PHY as that has already been done. + */ +int +ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok) +{ + struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; + struct ble_mbuf_hdr *hdr = BLE_MBUF_HDR_PTR(rxpdu); + struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; + uint8_t *rxbuf; + uint8_t pdu_type; + struct ble_ll_scan_addr_data addrd; + int rc; + + /* + * If buffer for incoming PDU was not allocated we need to force scan to be + * restarted since LL will not be notified. Keep PHY enabled. + */ + if (rxpdu == NULL) { + ble_ll_scan_interrupted(scansm); + return 0; + } + + rxbuf = rxpdu->om_data; + pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + /* + * In case aux was expected, copy aux_data for LL to use. Make sure this was + * indeed an aux as otherwise there's no need to process it and just pass to + * LL immediately. + */ + if (scansm->cur_aux_data) { + rxinfo->user_data = scansm->cur_aux_data; + scansm->cur_aux_data = NULL; + if (pdu_type != BLE_ADV_PDU_TYPE_ADV_EXT_IND) { + ble_ll_state_set(BLE_LL_STATE_STANDBY); + return -1; + } + } +#endif + + if (!crcok) { + goto scan_rx_isr_ignore; + } + + /* + * Addresses will be always set in handlers, no need to initialize them. We + * only need to initialize rl which may not be always set, depending on how + * filtering goes. + */ + addrd.rl = NULL; + + switch (pdu_type) { + case BLE_ADV_PDU_TYPE_ADV_IND: + case BLE_ADV_PDU_TYPE_ADV_DIRECT_IND: + case BLE_ADV_PDU_TYPE_ADV_NONCONN_IND: + case BLE_ADV_PDU_TYPE_SCAN_RSP: + case BLE_ADV_PDU_TYPE_ADV_SCAN_IND: + rc = ble_ll_scan_rx_isr_on_legacy(pdu_type, rxbuf, hdr, &addrd); + break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + case BLE_ADV_PDU_TYPE_ADV_EXT_IND: + rc = ble_ll_scan_rx_isr_on_aux(pdu_type, rxbuf, hdr, &addrd); + break; +#endif + default: + /* This is not something we would like to process here */ + rc = -1; + break; + } + + if (rc == -1) { + goto scan_rx_isr_ignore; + } else if (rc == 1) { + if (ble_ll_scan_send_scan_req(pdu_type, rxbuf, hdr, &addrd)) { + /* Keep PHY active and LL in scanning state */ + return 0; + } + } + + /* We are done with this PDU so go to standby and let LL resume if needed */ + ble_ll_state_set(BLE_LL_STATE_STANDBY); + return -1; + +scan_rx_isr_ignore: + rxinfo->flags |= BLE_MBUF_HDR_F_IGNORED; + ble_ll_state_set(BLE_LL_STATE_STANDBY); + return -1; +} + +/** + * Called to resume scanning. This is called after an advertising event or + * connection event has ended. It is also called if we receive a packet while + * in the initiating or scanning state. + * + * If periodic advertising is enabled this is also called on sync event end + * or sync packet received if chaining + * + * Context: Link Layer task + */ +void +ble_ll_scan_chk_resume(void) +{ + os_sr_t sr; + struct ble_ll_scan_sm *scansm; + uint32_t now; + + scansm = &g_ble_ll_scan_sm; + if (scansm->scan_enabled) { + OS_ENTER_CRITICAL(sr); + if (scansm->restart_timer_needed) { + scansm->restart_timer_needed = 0; + ble_ll_event_send(&scansm->scan_sched_ev); + STATS_INC(ble_ll_stats, scan_timer_restarted); + OS_EXIT_CRITICAL(sr); + return; + } + + now = os_cputime_get32(); + if (ble_ll_state_get() == BLE_LL_STATE_STANDBY && + ble_ll_scan_is_inside_window(scansm->scanp, now)) { + /* Turn on the receiver and set state */ + ble_ll_scan_start(scansm, NULL); + } + OS_EXIT_CRITICAL(sr); + } +} + +/** + * Scan timer callback; means that the scan window timeout has been reached + * and we should perform the appropriate actions. + * + * Context: Interrupt (cputimer) + * + * @param arg Pointer to scan state machine. + */ +void +ble_ll_scan_timer_cb(void *arg) +{ + struct ble_ll_scan_sm *scansm; + + scansm = (struct ble_ll_scan_sm *)arg; + ble_ll_event_send(&scansm->scan_sched_ev); +} + +void +ble_ll_scan_interrupted(struct ble_ll_scan_sm *scansm) +{ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + ble_npl_event_set_arg(&scansm->scan_interrupted_ev, scansm->cur_aux_data); + scansm->cur_aux_data = NULL; +#endif + + ble_ll_event_send(&scansm->scan_interrupted_ev); +} + +/** + * Called when the wait for response timer expires while in the scanning + * state. + * + * Context: Interrupt. + */ +void +ble_ll_scan_wfr_timer_exp(void) +{ + struct ble_ll_scan_sm *scansm; + uint8_t chan; + int phy; + int rc; +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + uint8_t phy_mode; +#endif + uint32_t now; + + scansm = &g_ble_ll_scan_sm; + + /* Update backoff if we failed to receive scan response */ + if (scansm->scan_rsp_pending) { + scansm->scan_rsp_pending = 0; + ble_ll_scan_req_backoff(scansm, 0); + } + + if (scansm->cur_aux_data) { + /* We actually care about interrupted scan only for EXT ADV because only + * then we might consider to send truncated event to the host. + */ + ble_ll_scan_interrupted(scansm); + + /* Need to disable phy since we are going to move to BLE_LL_STATE_STANDBY + * or we will need to change channel to primary one + */ + ble_phy_disable(); + + now = os_cputime_get32(); + if (!ble_ll_scan_is_inside_window(scansm->scanp, now)) { + /* Outside the window scan */ + ble_ll_state_set(BLE_LL_STATE_STANDBY); + return; + } + + ble_ll_get_chan_to_scan(scansm, &chan, &phy); +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + phy_mode = ble_ll_phy_to_phy_mode(phy, BLE_HCI_LE_PHY_CODED_ANY); + ble_phy_mode_set(phy_mode, phy_mode); +#endif + rc = ble_phy_setchan(chan, BLE_ACCESS_ADDR_ADV, BLE_LL_CRCINIT_ADV); + BLE_LL_ASSERT(rc == 0); + } + + + ble_phy_restart_rx(); +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +/* + * Send extended advertising report + * + * @return -1 on error (data truncated or other error) + * 0 on success (data status is "completed") + * 1 on success (data status is not "completed") + */ +static int +ble_ll_hci_send_ext_adv_report(uint8_t ptype, uint8_t *adva, uint8_t adva_type, + uint8_t *inita, uint8_t inita_type, + struct os_mbuf *om, + struct ble_mbuf_hdr *hdr) +{ + struct ble_ll_aux_data *aux_data = hdr->rxinfo.user_data; + struct ble_hci_ev_le_subev_ext_adv_rpt *ev; + struct ext_adv_report *report; + struct ble_hci_ev *hci_ev; + struct ble_hci_ev *hci_ev_next; + int offset; + int datalen; + int rc; + bool need_event; + bool is_scannable_aux; + uint8_t max_data_len; + + if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) { + rc = -1; + goto done; + } + + /* + * We keep one allocated event in aux_data to be able to truncate chain + * properly in case of error. If there is no event in aux_data it means this + * is the first event for this chain. + */ + if (aux_data && aux_data->evt) { + hci_ev = aux_data->evt; + aux_data->evt = NULL; + + hci_ev->length = sizeof(*ev) + sizeof(*report); + } else { + hci_ev = ble_ll_scan_get_ext_adv_report(NULL); + if (!hci_ev) { + rc = -1; + goto done; + } + } + + ev = (void *) hci_ev->data; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + /* If RPA has been used, make sure we use correct address types + * in the advertising report. + */ + if (BLE_MBUF_HDR_RESOLVED(hdr)) { + adva_type += 2; + } + if (BLE_MBUF_HDR_TARGETA_RESOLVED(hdr)) { + inita_type += 2; + } +#endif + + datalen = ble_ll_scan_parse_ext_hdr(om, adva, adva_type, inita, inita_type, + hdr, ev->reports); + if (datalen < 0) { + rc = -1; + + /* Need to send truncated event if we already sent some reports */ + if (aux_data && (aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_ANY)) { + BLE_LL_ASSERT(!(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_COMPLETED)); + BLE_LL_ASSERT(!(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED)); + + aux_data->flags_ll |= BLE_LL_AUX_FLAG_SCAN_ERROR; + aux_data->flags_ll |= BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED; + + report = ev->reports; + report->data_len = 0; + report->evt_type |= BLE_HCI_ADV_DATA_STATUS_TRUNCATED; + + ble_ll_hci_event_send(hci_ev); + goto done; + } + + ble_hci_trans_buf_free((uint8_t *)hci_ev); + goto done; + } + + is_scannable_aux = aux_data && + (aux_data->evt_type & BLE_HCI_ADV_SCAN_MASK) && + !(aux_data->evt_type & BLE_HCI_ADV_SCAN_RSP_MASK); + + max_data_len = BLE_LL_MAX_EVT_LEN - sizeof(*hci_ev) - sizeof(*ev) - sizeof(*report); + offset = 0; + + do { + hci_ev_next = NULL; + + ev = (void *) hci_ev->data; + report = ev->reports; + + report->data_len = min(max_data_len, datalen - offset); + + /* adjust event length */ + hci_ev->length += report->data_len; + report->rssi = hdr->rxinfo.rssi; + + os_mbuf_copydata(om, offset, report->data_len, report->data); + offset += report->data_len; + + /* + * We need another event if either there are still some data left to + * send in current PDU or scan is not completed. The only exception is + * when this is a scannable event which is not a scan response. + */ + need_event = ((offset < datalen) || (aux_data && !(aux_data->flags_ll & BLE_LL_AUX_FLAG_SCAN_COMPLETE))) && !is_scannable_aux; + + if (need_event) { + /* + * We will need another event so let's try to allocate one now. If + * we cannot do this, need to mark event as truncated. + */ + hci_ev_next = ble_ll_scan_get_ext_adv_report(report); + + if (hci_ev_next) { + report->evt_type |= BLE_HCI_ADV_DATA_STATUS_INCOMPLETE; + rc = 1; + } else { + report->evt_type |= BLE_HCI_ADV_DATA_STATUS_TRUNCATED; + rc = -1; + } + } else if (aux_data && (aux_data->flags_ll & BLE_LL_AUX_FLAG_SCAN_ERROR)) { + report->evt_type |= BLE_HCI_ADV_DATA_STATUS_TRUNCATED; + rc = -1; + } else { + rc = 0; + } + + if ((rc == -1) && aux_data) { + aux_data->flags_ll |= BLE_LL_AUX_FLAG_SCAN_ERROR; + + if (!(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_ANY)) { + ble_hci_trans_buf_free((uint8_t *)hci_ev); + goto done; + } + + aux_data->flags_ll |= BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED; + } else if (!is_scannable_aux) { + /* + * We do not set 'sent' flags for scannable AUX since we only care + * about scan response that will come next. + */ + aux_data->flags_ll |= BLE_LL_AUX_FLAG_HCI_SENT_ANY; + if (rc == 0) { + aux_data->flags_ll |= BLE_LL_AUX_FLAG_HCI_SENT_COMPLETED; + } + } + + ble_ll_hci_event_send(hci_ev); + + hci_ev = hci_ev_next; + } while ((offset < datalen) && hci_ev); + + BLE_LL_ASSERT(offset <= datalen); + + if (aux_data) { + /* Store any event left for later use */ + aux_data->evt = hci_ev; + } else { + /* If it is empty beacon, evt shall be NULL */ + BLE_LL_ASSERT(!hci_ev); + } + +done: + if (!aux_data) { + return rc; + } + + if (rc == 0) { + if (aux_data->evt_type & BLE_HCI_ADV_SCAN_RSP_MASK) { + /* Complete scan response can be added to duplicates list */ + ble_ll_scan_add_scan_rsp_adv(aux_data->adva, aux_data->adva_type, + 1, aux_data->adi); + } else if (is_scannable_aux) { + /* + * Scannable AUX is marked as incomplete because we do not want to + * add this to duplicates list now, this should happen only after + * we receive complete scan response. The drawback here is that we + * will keep receiving reports for scannable PDUs until complete + * scan response is received. + * + * XXX ^^ extend duplicates list to fix + */ + rc = 1; + } + } else if (rc < 0) { + aux_data->flags_ll |= BLE_LL_AUX_FLAG_SCAN_ERROR; + } + + return rc; +} +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) +static void +ble_ll_scan_check_periodic_sync(const struct os_mbuf *om, struct ble_mbuf_hdr *rxhdr, + uint8_t *adva, uint8_t adva_type, int rpa_index) +{ + uint8_t pdu_len; + uint8_t ext_hdr_len; + uint8_t ext_hdr_flags; + uint8_t *ext_hdr; + uint8_t *rxbuf = om->om_data; + uint8_t sid; + int i; + + pdu_len = rxbuf[1]; + if (pdu_len == 0) { + return; + } + + ext_hdr_len = rxbuf[2] & 0x3F; + + if (ext_hdr_len) { + ext_hdr_flags = rxbuf[3]; + ext_hdr = &rxbuf[4]; + i = 0; + + if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) { + i += BLE_LL_EXT_ADV_ADVA_SIZE; + } + + if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) { + i += BLE_LL_EXT_ADV_TARGETA_SIZE; + } + + if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_CTE_INFO_BIT)) { + i += 1; + } + + if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) { + sid = (get_le16(ext_hdr + i) >> 12); + i += BLE_LL_EXT_ADV_DATA_INFO_SIZE; + } else { + /* ADI is mandatory */ + return; + } + + if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) { + i += BLE_LL_EXT_ADV_AUX_PTR_SIZE; + } + + if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_SYNC_INFO_BIT)) { + ble_ll_sync_info_event(adva, adva_type, rpa_index, sid, rxhdr, + ext_hdr + i); + } + } +} +#endif + +static inline void +ble_ll_scan_dup_move_to_head(struct ble_ll_scan_dup_entry *e) +{ + if (e != TAILQ_FIRST(&g_scan_dup_list)) { + TAILQ_REMOVE(&g_scan_dup_list, e, link); + TAILQ_INSERT_HEAD(&g_scan_dup_list, e, link); + } +} + +static inline struct ble_ll_scan_dup_entry * +ble_ll_scan_dup_new(void) +{ + struct ble_ll_scan_dup_entry *e; + + e = os_memblock_get(&g_scan_dup_pool); + if (!e) { + e = TAILQ_LAST(&g_scan_dup_list, ble_ll_scan_dup_list); + TAILQ_REMOVE(&g_scan_dup_list, e, link); + } + + memset(e, 0, sizeof(*e)); + + return e; +} + +static int +ble_ll_scan_dup_check_legacy(uint8_t addr_type, uint8_t *addr, uint8_t pdu_type) +{ + struct ble_ll_scan_dup_entry *e; + uint8_t type; + int rc; + + type = BLE_LL_SCAN_ENTRY_TYPE_LEGACY(addr_type); + + TAILQ_FOREACH(e, &g_scan_dup_list, link) { + if ((e->type == type) && !memcmp(e->addr, addr, 6)) { + break; + } + } + + if (e) { + if (pdu_type == BLE_ADV_PDU_TYPE_ADV_DIRECT_IND) { + rc = e->flags & BLE_LL_SCAN_DUP_F_DIR_ADV_REPORT_SENT; + } else if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_RSP) { + rc = e->flags & BLE_LL_SCAN_DUP_F_SCAN_RSP_SENT; + } else { + rc = e->flags & BLE_LL_SCAN_DUP_F_ADV_REPORT_SENT; + } + + ble_ll_scan_dup_move_to_head(e); + } else { + rc = 0; + + e = ble_ll_scan_dup_new(); + e->flags = 0; + e->type = type; + memcpy(e->addr, addr, 6); + + TAILQ_INSERT_HEAD(&g_scan_dup_list, e, link); + } + + return rc; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +static int +ble_ll_scan_dup_check_ext(uint8_t addr_type, uint8_t *addr, + struct ble_ll_aux_data *aux_data) +{ + struct ble_ll_scan_dup_entry *e; + bool has_aux; + bool is_anon; + uint16_t adi; + uint8_t type; + int rc; + + has_aux = aux_data != NULL; + is_anon = addr == NULL; + adi = has_aux ? aux_data->adi : 0; + + type = BLE_LL_SCAN_ENTRY_TYPE_EXT(addr_type, has_aux, is_anon, adi); + + TAILQ_FOREACH(e, &g_scan_dup_list, link) { + if ((e->type == type) && + (is_anon || !memcmp(e->addr, addr, BLE_DEV_ADDR_LEN))) { + break; + } + } + + if (e) { + if (e->adi != adi) { + rc = 0; + + e->flags = 0; + e->adi = adi; + } else { + rc = e->flags & BLE_LL_SCAN_DUP_F_ADV_REPORT_SENT; + } + + ble_ll_scan_dup_move_to_head(e); + } else { + rc = 0; + + e = ble_ll_scan_dup_new(); + e->flags = 0; + e->type = type; + e->adi = adi; + if (!is_anon) { + memcpy(e->addr, addr, 6); + } + + TAILQ_INSERT_HEAD(&g_scan_dup_list, e, link); + } + + return rc; +} + +static int +ble_ll_scan_dup_update_ext(uint8_t addr_type, uint8_t *addr, + struct ble_ll_aux_data *aux_data) +{ + struct ble_ll_scan_dup_entry *e; + bool has_aux; + bool is_anon; + uint16_t adi; + uint8_t type; + + has_aux = aux_data != NULL; + is_anon = addr == NULL; + adi = has_aux ? aux_data->adi : 0; + + type = BLE_LL_SCAN_ENTRY_TYPE_EXT(addr_type, has_aux, is_anon, adi); + + /* + * We assume ble_ll_scan_dup_check() was called before which either matched + * some entry or allocated new one and placed in on the top of queue. + */ + + e = TAILQ_FIRST(&g_scan_dup_list); + BLE_LL_ASSERT(e && e->type == type && (is_anon || !memcmp(e->addr, addr, 6))); + + e->flags |= BLE_LL_SCAN_DUP_F_ADV_REPORT_SENT; + + return 0; +} +#endif + +static void +ble_ll_scan_rx_pkt_in_restore_addr_data(struct ble_mbuf_hdr *hdr, + struct ble_ll_scan_addr_data *addrd) +{ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; + struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; + struct ble_ll_resolv_entry *rl; +#endif + + addrd->adv_addr = addrd->adva; + addrd->adv_addr_type = addrd->adva_type; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + if (rxinfo->rpa_index >= 0) { + rl = &g_ble_ll_resolv_list[rxinfo->rpa_index]; + addrd->adv_addr = rl->rl_identity_addr; + addrd->adv_addr_type = rl->rl_addr_type; + addrd->rl = rl; + } + if (hdr->rxinfo.flags & BLE_MBUF_HDR_F_TARGETA_RESOLVED) { + addrd->targeta = ble_ll_get_our_devaddr(scansm->own_addr_type & 1); + addrd->targeta_type = scansm->own_addr_type & 1; + } +#endif +} + +static void +ble_ll_scan_rx_pkt_in_on_legacy(uint8_t pdu_type, struct os_mbuf *om, + struct ble_mbuf_hdr *hdr, + struct ble_ll_scan_addr_data *addrd) +{ + struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; + uint8_t *rxbuf = om->om_data; + bool send_hci_report; + + + if (!BLE_MBUF_HDR_DEVMATCH(hdr) || + !BLE_MBUF_HDR_CRC_OK(hdr) || + BLE_MBUF_HDR_IGNORED(hdr)) { + return; + } + + ble_ll_scan_get_addr_data_from_legacy(pdu_type, rxbuf, addrd); + ble_ll_scan_rx_pkt_in_restore_addr_data(hdr, addrd); + + send_hci_report = !scansm->scan_filt_dups || + !ble_ll_scan_dup_check_legacy(addrd->adv_addr_type, + addrd->adv_addr, + pdu_type); + if (send_hci_report) { + /* Sending advertising report will also update scan_dup list */ + ble_ll_scan_send_adv_report(pdu_type, + addrd->adv_addr, addrd->adv_addr_type, + addrd->targeta, addrd->targeta_type, + om, hdr, scansm); + } + + if (BLE_MBUF_HDR_SCAN_RSP_RXD(hdr)) { + ble_ll_scan_req_backoff(scansm, 1); + } +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +static void +ble_ll_scan_rx_pkt_in_on_aux(uint8_t pdu_type, struct os_mbuf *om, + struct ble_mbuf_hdr *hdr, + struct ble_ll_scan_addr_data *addrd) +{ + struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + uint8_t *rxbuf = om->om_data; +#endif + struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; + struct ble_ll_aux_data *aux_data = rxinfo->user_data; + bool send_hci_report; + int rc; + + if (!scansm->ext_scanning) { + goto scan_continue; + } + + if (aux_data) { + aux_data->flags_ll |= aux_data->flags_isr; + } + + /* + * For every new extended advertising event scanned, rx_isr_end will either + * allocate new aux_data or set 'invalid' flag. This means if no 'invalid' + * flag is set, aux_data is always valid. + */ + + /* Drop on scan error or if we received not what we expected to receive */ + if (!BLE_MBUF_HDR_CRC_OK(hdr) || + BLE_MBUF_HDR_IGNORED(hdr) || + BLE_MBUF_HDR_AUX_INVALID(hdr) || + (aux_data->flags_ll & BLE_LL_AUX_FLAG_SCAN_ERROR) || + (pdu_type != BLE_ADV_PDU_TYPE_ADV_EXT_IND)) { + if (aux_data) { + ble_ll_scan_end_adv_evt(aux_data); + ble_ll_scan_aux_data_unref(aux_data); + rxinfo->user_data = NULL; + } + return; + } + + BLE_LL_ASSERT(aux_data); + + if (aux_data->flags & BLE_LL_AUX_HAS_ADVA) { + addrd->adva = aux_data->adva; + addrd->adva_type = aux_data->adva_type; + } else { + addrd->adva = NULL; + addrd->adva_type = 0; + } + if (aux_data->flags & BLE_LL_AUX_HAS_TARGETA) { + addrd->targeta = aux_data->targeta; + addrd->targeta_type = aux_data->targeta_type; + } else { + addrd->targeta = NULL; + addrd->targeta_type = 0; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + /* + * Periodic scan uses own filter list so we need to let it do own filtering + * regardless of scanner filtering. Just make sure we already have AdvA. + */ + if (ble_ll_sync_enabled() && + ((rxbuf[2] >> 6) == BLE_LL_EXT_ADV_MODE_NON_CONN) && addrd->adva && + !(aux_data->flags_ll & BLE_LL_AUX_FLAG_AUX_CHAIN_RECEIVED)) { + ble_ll_scan_check_periodic_sync(om, hdr, addrd->adva, addrd->adva_type, + rxinfo->rpa_index); + } +#endif + + /* Ignore if device was not matched by either whitelist or scan policy */ + if (!BLE_MBUF_HDR_DEVMATCH(hdr)) { + goto scan_continue; + } + + ble_ll_scan_rx_pkt_in_restore_addr_data(hdr, addrd); + + /* + * If there is AuxPtr in this PDU, we should first try to schedule scan for + * subsequent aux. + */ + if (BLE_MBUF_HDR_WAIT_AUX(hdr)) { + if (ble_ll_sched_aux_scan(hdr, scansm, aux_data)) { + rxinfo->flags &= ~BLE_MBUF_HDR_F_AUX_PTR_WAIT; + aux_data->flags_ll |= BLE_LL_AUX_FLAG_SCAN_ERROR; + + /* Silently ignore if no HCI event was sent to host */ + if (!(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_ANY)) { + goto scan_continue; + } + } + + /* Ignore if this was just ADV_EXT_IND with AuxPtr, will process aux */ + if (!(aux_data->flags_ll & BLE_LL_AUX_FLAG_AUX_ADV_RECEIVED)) { + goto scan_continue; + } + + STATS_INC(ble_ll_stats, aux_chain_cnt); + } + + send_hci_report = !scansm->scan_filt_dups || + !ble_ll_scan_dup_check_ext(addrd->adv_addr_type, + addrd->adv_addr, aux_data); + if (send_hci_report) { + rc = ble_ll_hci_send_ext_adv_report(pdu_type, + addrd->adv_addr, addrd->adv_addr_type, + addrd->targeta, addrd->targeta_type, + om, hdr); + if ((rc < 0) && BLE_MBUF_HDR_WAIT_AUX(hdr)) { + /* Data were truncated so stop scanning for subsequent auxes */ + aux_data->flags_ll |= BLE_LL_AUX_FLAG_SCAN_ERROR; + + if (ble_ll_sched_rmv_elem(&aux_data->sch) == 0) { + ble_ll_scan_aux_data_unref(aux_data->sch.cb_arg); + aux_data->sch.cb_arg = NULL; + } + } else if ((rc == 0) && scansm->scan_filt_dups) { + /* Complete data were send so we can update scan_dup list */ + ble_ll_scan_dup_update_ext(addrd->adv_addr_type, addrd->adv_addr, + aux_data); + } + } + + if (BLE_MBUF_HDR_SCAN_RSP_RXD(hdr)) { + /* + * For now assume success if we just received direct scan response, + * don't care about complete aux chain. + */ + ble_ll_scan_req_backoff(scansm, 1); + } + +scan_continue: + ble_ll_scan_aux_data_unref(rxinfo->user_data); + rxinfo->user_data = NULL; +} +#endif + +/** + * Process a received PDU while in the scanning state. + * + * Context: Link Layer task. + * + * @param pdu_type + * @param rxbuf + */ +void +ble_ll_scan_rx_pkt_in(uint8_t ptype, struct os_mbuf *om, struct ble_mbuf_hdr *hdr) +{ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; + struct ble_ll_aux_data *aux_data = rxinfo->user_data; +#endif + struct ble_ll_scan_addr_data addrd; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (aux_data || (ptype == BLE_ADV_PDU_TYPE_ADV_EXT_IND)) { + ble_ll_scan_rx_pkt_in_on_aux(ptype, om, hdr, &addrd); + ble_ll_scan_chk_resume(); + return; + } +#endif + + ble_ll_scan_rx_pkt_in_on_legacy(ptype, om, hdr, &addrd); + ble_ll_scan_chk_resume(); +} + +int +ble_ll_scan_set_scan_params(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_set_scan_params_cp *cmd = (const void *)cmdbuf; + uint16_t scan_itvl; + uint16_t scan_window; + struct ble_ll_scan_sm *scansm; + struct ble_ll_scan_params *scanp; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* If already enabled, we return an error */ + scansm = &g_ble_ll_scan_sm; + if (scansm->scan_enabled) { + return BLE_ERR_CMD_DISALLOWED; + } + + /* Get the scan interval and window */ + scan_itvl = le16toh(cmd->scan_itvl); + scan_window = le16toh(cmd->scan_window); + + /* Check scan type */ + if ((cmd->scan_type != BLE_HCI_SCAN_TYPE_PASSIVE) && + (cmd->scan_type != BLE_HCI_SCAN_TYPE_ACTIVE)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Check interval and window */ + if ((scan_itvl < BLE_HCI_SCAN_ITVL_MIN) || + (scan_itvl > BLE_HCI_SCAN_ITVL_MAX) || + (scan_window < BLE_HCI_SCAN_WINDOW_MIN) || + (scan_window > BLE_HCI_SCAN_WINDOW_MAX) || + (scan_itvl < scan_window)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Check own addr type */ + if (cmd->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Check scanner filter policy */ + if (cmd->filter_policy > BLE_HCI_SCAN_FILT_MAX) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Store scan parameters */ + scanp = &g_ble_ll_scan_params[PHY_UNCODED]; + scanp->configured = 1; + scanp->scan_type = cmd->scan_type; + scanp->timing.interval = ble_ll_scan_time_hci_to_ticks(scan_itvl); + scanp->timing.window = ble_ll_scan_time_hci_to_ticks(scan_window); + scanp->scan_filt_policy = cmd->filter_policy; + scanp->own_addr_type = cmd->own_addr_type; + +#if (BLE_LL_SCAN_PHY_NUMBER == 2) + g_ble_ll_scan_params[PHY_CODED].configured = 0; +#endif + + return 0; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +static int +ble_ll_check_scan_params(uint8_t type, uint16_t itvl, uint16_t window) +{ + /* Check scan type */ + if ((type != BLE_HCI_SCAN_TYPE_PASSIVE) && + (type != BLE_HCI_SCAN_TYPE_ACTIVE)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Check interval and window */ + if ((itvl < BLE_HCI_SCAN_ITVL_MIN) || + (itvl > BLE_HCI_SCAN_ITVL_MAX) || + (window < BLE_HCI_SCAN_WINDOW_MIN) || + (window > BLE_HCI_SCAN_WINDOW_MAX) || + (itvl < window)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + return 0; +} + +int +ble_ll_set_ext_scan_params(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_set_ext_scan_params_cp *cmd = (const void *) cmdbuf; + const struct scan_params *params = cmd->scans; + + struct ble_ll_scan_params new_params[BLE_LL_SCAN_PHY_NUMBER] = { }; + struct ble_ll_scan_params *uncoded = &new_params[PHY_UNCODED]; + struct ble_ll_scan_params *coded = &new_params[PHY_CODED]; + uint16_t interval; + uint16_t window; + int rc; + + if (len <= sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + len -= sizeof(*cmd); + + /* If already enabled, we return an error */ + if (g_ble_ll_scan_sm.scan_enabled) { + return BLE_ERR_CMD_DISALLOWED; + } + + /* Check own addr type */ + if (cmd->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + coded->own_addr_type = cmd->own_addr_type; + uncoded->own_addr_type = cmd->own_addr_type; + + /* Check scanner filter policy */ + if (cmd->filter_policy > BLE_HCI_SCAN_FILT_MAX) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + coded->scan_filt_policy = cmd->filter_policy; + uncoded->scan_filt_policy = cmd->filter_policy; + + /* Check if no reserved bits in PHYS are set and that at least one valid PHY + * is set. + */ + if (!(cmd->phys & SCAN_VALID_PHY_MASK) || + (cmd->phys & ~SCAN_VALID_PHY_MASK)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (cmd->phys & BLE_HCI_LE_PHY_1M_PREF_MASK) { + if (len < sizeof(*params)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + interval = le16toh(params->itvl); + window = le16toh(params->window); + + rc = ble_ll_check_scan_params(params->type, interval, window); + if (rc) { + return rc; + } + + uncoded->scan_type = params->type; + uncoded->timing.interval = ble_ll_scan_time_hci_to_ticks(interval); + uncoded->timing.window = ble_ll_scan_time_hci_to_ticks(window); + + /* That means user wants to use this PHY for scanning */ + uncoded->configured = 1; + params++; + len -= sizeof(*params); + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + if (cmd->phys & BLE_HCI_LE_PHY_CODED_PREF_MASK) { + if (len < sizeof(*params)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + interval = le16toh(params->itvl); + window = le16toh(params->window); + + rc = ble_ll_check_scan_params(params->type, interval, window); + if (rc) { + return rc; + } + + coded->scan_type = params->type; + coded->timing.interval = ble_ll_scan_time_hci_to_ticks(interval); + coded->timing.window = ble_ll_scan_time_hci_to_ticks(window); + + /* That means user wants to use this PHY for scanning */ + coded->configured = 1; + } +#endif + + /* if any of PHYs is configured for continuous scan we alter interval to + * fit other PHY + */ + if (coded->configured && uncoded->configured) { + if (coded->timing.interval == coded->timing.window) { + coded->timing.interval += uncoded->timing.window; + } + + if (uncoded->timing.interval == uncoded->timing.window) { + uncoded->timing.window += coded->timing.window; + } + } + + memcpy(g_ble_ll_scan_params, new_params, sizeof(new_params)); + + return 0; +} + +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +static void +ble_ll_scan_duration_period_timers_restart(struct ble_ll_scan_sm *scansm) +{ + uint32_t now; + + now = os_cputime_get32(); + + os_cputime_timer_stop(&scansm->duration_timer); + os_cputime_timer_stop(&scansm->period_timer); + + if (scansm->duration_ticks) { + os_cputime_timer_start(&scansm->duration_timer, + now + scansm->duration_ticks); + + if (scansm->period_ticks) { + os_cputime_timer_start(&scansm->period_timer, + now + scansm->period_ticks); + } + } +} + +static void +ble_ll_scan_duration_timer_cb(void *arg) +{ + struct ble_ll_scan_sm *scansm; + + scansm = (struct ble_ll_scan_sm *)arg; + + ble_ll_scan_sm_stop(2); + + /* if period is set both timers get started from period cb */ + if (!scansm->period_ticks) { + ble_ll_hci_ev_send_scan_timeout(); + } +} + +static void +ble_ll_scan_period_timer_cb(void *arg) +{ + struct ble_ll_scan_sm *scansm = arg; + + ble_ll_scan_sm_start(scansm); + + /* always start timer regardless of ble_ll_scan_sm_start result + * if it failed will restart in next period + */ + ble_ll_scan_duration_period_timers_restart(scansm); +} +#endif + +/** + * ble ll scan set enable + * + * HCI scan set enable command processing function + * + * Context: Link Layer task (HCI Command parser). + * + * @return int BLE error code. + */ +static int +ble_ll_scan_set_enable(uint8_t enable, uint8_t filter_dups, uint16_t period, + uint16_t dur, bool ext) +{ + int rc; + struct ble_ll_scan_sm *scansm; + struct ble_ll_scan_params *scanp; + struct ble_ll_scan_params *scanp_phy; + int i; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + uint32_t period_ticks = 0; + uint32_t dur_ticks = 0; +#endif + + /* Check for valid parameters */ + if ((filter_dups > 1) || (enable > 1)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + scansm = &g_ble_ll_scan_sm; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + /* we can do that here since value will never change until reset */ + scansm->ext_scanning = ext; + + if (ext) { + /* Period parameter is ignored when the Duration parameter is zero */ + if (!dur) { + period = 0; + } + + /* period is in 1.28 sec units + * TODO support full range, would require os_cputime milliseconds API + */ + if (period > 3355) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + period_ticks = os_cputime_usecs_to_ticks(period * 1280000); + + /* duration is in 10ms units */ + dur_ticks = os_cputime_usecs_to_ticks(dur * 10000); + + if (dur_ticks && period_ticks && (dur_ticks >= period_ticks)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + } +#endif + + /* disable*/ + if (!enable) { + if (scansm->scan_enabled) { + ble_ll_scan_sm_stop(1); + } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + os_cputime_timer_stop(&scansm->duration_timer); + os_cputime_timer_stop(&scansm->period_timer); +#endif + + return BLE_ERR_SUCCESS; + } + + /* if already enable we just need to update parameters */ + if (scansm->scan_enabled) { + /* Controller does not allow initiating and scanning.*/ + for (i = 0; i < BLE_LL_SCAN_PHY_NUMBER; i++) { + scanp_phy = &scansm->scanp_phys[i]; + if (scanp_phy->configured && + scanp_phy->scan_type == BLE_SCAN_TYPE_INITIATE) { + return BLE_ERR_CMD_DISALLOWED; + } + } + +#if MYNEWT_VAL(BLE_LL_NUM_SCAN_DUP_ADVS) + /* update filter policy */ + scansm->scan_filt_dups = filter_dups; +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + /* restart timers according to new settings */ + scansm->duration_ticks = dur_ticks; + scansm->period_ticks = period_ticks; + ble_ll_scan_duration_period_timers_restart(scansm); +#endif + + return BLE_ERR_SUCCESS; + } + + /* we can store those upfront regardless of start scan result since scan is + * disabled now + */ + +#if MYNEWT_VAL(BLE_LL_NUM_SCAN_DUP_ADVS) + scansm->scan_filt_dups = filter_dups; +#endif + scansm->scanp = NULL; + scansm->scanp_next = NULL; + + for (i = 0; i < BLE_LL_SCAN_PHY_NUMBER; i++) { + scanp_phy = &scansm->scanp_phys[i]; + scanp = &g_ble_ll_scan_params[i]; + + if (!scanp->configured) { + continue; + } + + scanp_phy->configured = scanp->configured; + scanp_phy->scan_type = scanp->scan_type; + scanp_phy->timing = scanp->timing; + scanp_phy->scan_filt_policy = scanp->scan_filt_policy; + scanp_phy->own_addr_type = scanp->own_addr_type; + + if (!scansm->scanp) { + scansm->scanp = scanp_phy; + /* Take own_addr_type from the first configured PHY. + * Note: All configured PHYs shall have the same own_addr_type + */ + scansm->own_addr_type = scanp_phy->own_addr_type; + } else { + scansm->scanp_next = scanp_phy; + } + } + + /* spec is not really clear if we should use defaults in this case + * or just disallow starting scan without explicit configuration + * For now be nice to host and just use values based on LE Set Scan + * Parameters defaults. + */ + if (!scansm->scanp) { + scansm->scanp = &scansm->scanp_phys[PHY_UNCODED]; + scansm->own_addr_type = BLE_ADDR_PUBLIC; + + scanp_phy = scansm->scanp; + scanp_phy->configured = 1; + scanp_phy->scan_type = BLE_SCAN_TYPE_PASSIVE; + scanp_phy->timing.interval = + ble_ll_scan_time_hci_to_ticks(BLE_HCI_SCAN_ITVL_DEF); + scanp_phy->timing.window = + ble_ll_scan_time_hci_to_ticks(BLE_HCI_SCAN_WINDOW_DEF); + scanp_phy->scan_filt_policy = BLE_HCI_SCAN_FILT_NO_WL; + scanp_phy->own_addr_type = BLE_ADDR_PUBLIC; + } + + rc = ble_ll_scan_sm_start(scansm); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (rc == BLE_ERR_SUCCESS) { + scansm->duration_ticks = dur_ticks; + scansm->period_ticks = period_ticks; + ble_ll_scan_duration_period_timers_restart(scansm); + } +#endif + + return rc; +} + +int ble_ll_hci_scan_set_enable(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_set_scan_enable_cp *cmd = (const void *) cmdbuf; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + return ble_ll_scan_set_enable(cmd->enable, cmd->filter_duplicates, 0, 0, + false); +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +int ble_ll_hci_ext_scan_set_enable(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_set_ext_scan_enable_cp *cmd = (const void *) cmdbuf; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + return ble_ll_scan_set_enable(cmd->enable, cmd->filter_dup, + le16toh(cmd->period), le16toh(cmd->duration), + true); +} +#endif + +/** + * Checks if controller can change the whitelist. If scanning is enabled and + * using the whitelist the controller is not allowed to change the whitelist. + * + * @return int 0: not allowed to change whitelist; 1: change allowed. + */ +int +ble_ll_scan_can_chg_whitelist(void) +{ + int rc; + struct ble_ll_scan_sm *scansm; + struct ble_ll_scan_params *scanp; + + scansm = &g_ble_ll_scan_sm; + scanp = scansm->scanp; + if (scansm->scan_enabled && (scanp->scan_filt_policy & 1)) { + rc = 0; + } else { + rc = 1; + } + + return rc; +} + +int +ble_ll_scan_initiator_start(struct hci_create_conn *hcc, + struct ble_ll_scan_sm **sm) +{ + struct ble_ll_scan_sm *scansm; + struct ble_ll_scan_params *scanp; + int rc; + + scansm = &g_ble_ll_scan_sm; + scansm->own_addr_type = hcc->own_addr_type; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + scansm->ext_scanning = 0; +#endif + scansm->scanp = &scansm->scanp_phys[PHY_UNCODED]; + scansm->scanp_next = NULL; + + scanp = scansm->scanp; + scanp->scan_filt_policy = hcc->filter_policy; + scanp->timing.interval = ble_ll_scan_time_hci_to_ticks(hcc->scan_itvl); + scanp->timing.window = ble_ll_scan_time_hci_to_ticks(hcc->scan_window); + scanp->scan_type = BLE_SCAN_TYPE_INITIATE; + + rc = ble_ll_scan_sm_start(scansm); + if (sm == NULL) { + return rc; + } + + if (rc == BLE_ERR_SUCCESS) { + *sm = scansm; + } else { + *sm = NULL; + } + + return rc; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +int +ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc, + struct ble_ll_scan_sm **sm) +{ + struct ble_ll_scan_sm *scansm; + struct ble_ll_scan_params *scanp_uncoded; + struct ble_ll_scan_params *scanp_coded; + struct hci_ext_conn_params *params; + int rc; + + scansm = &g_ble_ll_scan_sm; + scansm->own_addr_type = hcc->own_addr_type; + scansm->scanp = NULL; + scansm->scanp_next = NULL; + scansm->ext_scanning = 1; + + if (hcc->init_phy_mask & BLE_PHY_MASK_1M) { + params = &hcc->params[0]; + scanp_uncoded = &scansm->scanp_phys[PHY_UNCODED]; + + scanp_uncoded->timing.interval = ble_ll_scan_time_hci_to_ticks(params->scan_itvl); + scanp_uncoded->timing.window = ble_ll_scan_time_hci_to_ticks(params->scan_window); + scanp_uncoded->scan_type = BLE_SCAN_TYPE_INITIATE; + scanp_uncoded->scan_filt_policy = hcc->filter_policy; + scansm->scanp = scanp_uncoded; + } + + if (hcc->init_phy_mask & BLE_PHY_MASK_CODED) { + params = &hcc->params[2]; + scanp_coded = &scansm->scanp_phys[PHY_CODED]; + + scanp_coded->timing.interval = ble_ll_scan_time_hci_to_ticks(params->scan_itvl); + scanp_coded->timing.window = ble_ll_scan_time_hci_to_ticks(params->scan_window); + scanp_coded->scan_type = BLE_SCAN_TYPE_INITIATE; + scanp_coded->scan_filt_policy = hcc->filter_policy; + if (scansm->scanp) { + scansm->scanp_next = scanp_coded; + } else { + scansm->scanp = scanp_coded; + } + } + + /* if any of PHYs is configured for continuous scan we alter interval to + * fit other PHY + */ + if (scansm->scanp && scansm->scanp_next && scanp_coded->configured && + scanp_uncoded->configured) { + if (scanp_coded->timing.interval == scanp_coded->timing.window) { + scanp_coded->timing.interval += scanp_uncoded->timing.window; + } + + if (scanp_uncoded->timing.interval == scanp_uncoded->timing.window) { + scanp_uncoded->timing.interval += scanp_coded->timing.window; + } + } + + rc = ble_ll_scan_sm_start(scansm); + if (sm == NULL) { + return rc; + } + + if (rc == BLE_ERR_SUCCESS) { + *sm = scansm; + } else { + *sm = NULL; + } + + return rc; +} +#endif + +/** + * Checks to see if the scanner is enabled. + * + * @return int 0: not enabled; enabled otherwise + */ +int +ble_ll_scan_enabled(void) +{ + return (int)g_ble_ll_scan_sm.scan_enabled; +} + +/** + * Returns the peer resolvable private address of last device connecting to us + * + * @return uint8_t* + */ +uint8_t * +ble_ll_scan_get_peer_rpa(void) +{ + struct ble_ll_scan_sm *scansm; + + /* XXX: should this go into IRK list or connection? */ + scansm = &g_ble_ll_scan_sm; + return scansm->scan_peer_rpa; +} + +/** + * Returns the local resolvable private address currently being using by + * the scanner/initiator + * + * @return uint8_t* + */ +uint8_t * +ble_ll_scan_get_local_rpa(void) +{ + return g_ble_ll_scan_sm.pdu_data.scana; +} + +/** + * Set the Resolvable Private Address in the scanning (or initiating) state + * machine. + * + * XXX: should this go into IRK list or connection? + * + * @param rpa + */ +void +ble_ll_scan_set_peer_rpa(uint8_t *rpa) +{ + struct ble_ll_scan_sm *scansm; + + scansm = &g_ble_ll_scan_sm; + memcpy(scansm->scan_peer_rpa, rpa, BLE_DEV_ADDR_LEN); +} + +struct ble_ll_scan_pdu_data * +ble_ll_scan_get_pdu_data(void) +{ + return &g_ble_ll_scan_sm.pdu_data; +} + +/* Returns true if whitelist is enabled for scanning */ +int +ble_ll_scan_whitelist_enabled(void) +{ + return g_ble_ll_scan_sm.scanp->scan_filt_policy & 1; +} + +static void +ble_ll_scan_common_init(void) +{ + struct ble_ll_scan_sm *scansm; + struct ble_ll_scan_params *scanp; + int i; + + /* Clear state machine in case re-initialized */ + scansm = &g_ble_ll_scan_sm; + memset(scansm, 0, sizeof(struct ble_ll_scan_sm)); + + /* Clear scan parameters in case re-initialized */ + memset(g_ble_ll_scan_params, 0, sizeof(g_ble_ll_scan_params)); + + /* Initialize scanning window end event */ + ble_npl_event_init(&scansm->scan_sched_ev, ble_ll_scan_event_proc, scansm); + + for (i = 0; i < BLE_LL_SCAN_PHY_NUMBER; i++) { + /* Set all non-zero default parameters */ + scanp = &g_ble_ll_scan_params[i]; + scanp->timing.interval = + ble_ll_scan_time_hci_to_ticks(BLE_HCI_SCAN_ITVL_DEF); + scanp->timing.window = + ble_ll_scan_time_hci_to_ticks(BLE_HCI_SCAN_WINDOW_DEF); + } + + scansm->scanp_phys[PHY_UNCODED].phy = BLE_PHY_1M; +#if (BLE_LL_SCAN_PHY_NUMBER == 2) + scansm->scanp_phys[PHY_CODED].phy = BLE_PHY_CODED; +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + /* Make sure we'll generate new NRPA if necessary */ + scansm->scan_nrpa_timer = ble_npl_time_get(); +#endif + + /* Initialize scanning timer */ + os_cputime_timer_init(&scansm->scan_timer, ble_ll_scan_timer_cb, scansm); + + /* Initialize extended scan timers */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + os_cputime_timer_init(&scansm->duration_timer, + ble_ll_scan_duration_timer_cb, scansm); + os_cputime_timer_init(&scansm->period_timer, ble_ll_scan_period_timer_cb, + scansm); +#endif + + ble_npl_event_init(&scansm->scan_interrupted_ev, ble_ll_scan_interrupted_event_cb, NULL); +} + +/** + * Called when the controller receives the reset command. Resets the + * scanning state machine to its initial state. + * + * @return int + */ +void +ble_ll_scan_reset(void) +{ + struct ble_ll_scan_sm *scansm; + + scansm = &g_ble_ll_scan_sm; + + /* If enabled, stop it. */ + if (scansm->scan_enabled) { + ble_ll_scan_sm_stop(0); + } + + /* stop extended scan timers */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + os_cputime_timer_stop(&scansm->duration_timer); + os_cputime_timer_stop(&scansm->period_timer); +#endif + + /* Reset duplicate advertisers and those from which we rxd a response */ + g_ble_ll_scan_num_rsp_advs = 0; + memset(&g_ble_ll_scan_rsp_advs[0], 0, sizeof(g_ble_ll_scan_rsp_advs)); + + os_mempool_clear(&g_scan_dup_pool); + TAILQ_INIT(&g_scan_dup_list); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + /* clear memory pool for AUX scan results */ + os_mempool_clear(&ext_scan_aux_pool); +#endif + + /* Call the common init function again */ + ble_ll_scan_common_init(); +} + +/** + * ble ll scan init + * + * Initialize a scanner. Must be called before scanning can be started. + * Expected to be called with a un-initialized scanning state machine. + */ +void +ble_ll_scan_init(void) +{ + os_error_t err; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + err = os_mempool_init(&ext_scan_aux_pool, + MYNEWT_VAL(BLE_LL_EXT_ADV_AUX_PTR_CNT), + sizeof (struct ble_ll_aux_data), + ext_scan_aux_mem, + "ble_ll_aux_scan_pool"); + BLE_LL_ASSERT(err == 0); +#endif + + err = os_mempool_init(&g_scan_dup_pool, + MYNEWT_VAL(BLE_LL_NUM_SCAN_DUP_ADVS), + sizeof(struct ble_ll_scan_dup_entry), + g_scan_dup_mem, + "ble_ll_scan_dup_pool"); + BLE_LL_ASSERT(err == 0); + + TAILQ_INIT(&g_scan_dup_list); + + ble_ll_scan_common_init(); +} + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_sched.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_sched.c new file mode 100644 index 000000000..77c107f82 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_sched.c @@ -0,0 +1,1838 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef ESP_PLATFORM + +#include +#include +#include +#include +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/porting/nimble/include/os/os_cputime.h" + +#if defined(ARDUINO_ARCH_NRF5) && defined(NRF51) +#include "nimble/nimble/drivers/nrf51/include/ble/xcvr.h" +#elif defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) +#include "nimble/nimble/drivers/nrf52/include/ble/xcvr.h" +#endif + +#include "../include/controller/ble_phy.h" +#include "../include/controller/ble_ll.h" +#include "../include/controller/ble_ll_sched.h" +#include "../include/controller/ble_ll_adv.h" +#include "../include/controller/ble_ll_scan.h" +#include "../include/controller/ble_ll_rfmgmt.h" +#include "../include/controller/ble_ll_trace.h" +#include "../include/controller/ble_ll_sync.h" +#include "ble_ll_priv.h" +#include "ble_ll_conn_priv.h" + +/* XXX: this is temporary. Not sure what I want to do here */ +struct hal_timer g_ble_ll_sched_timer; + +uint8_t g_ble_ll_sched_offset_ticks; + +#define BLE_LL_SCHED_ADV_WORST_CASE_USECS \ + (BLE_LL_SCHED_MAX_ADV_PDU_USECS + BLE_LL_IFS + BLE_LL_SCHED_ADV_MAX_USECS \ + + XCVR_TX_SCHED_DELAY_USECS) + +#if (BLE_LL_SCHED_DEBUG == 1) +int32_t g_ble_ll_sched_max_late; +int32_t g_ble_ll_sched_max_early; +#endif + +/* XXX: TODO: + * 1) Add some accounting to the schedule code to see how late we are + * (min/max?) + * + * 2) Need to determine how we really want to handle the case when we execute + * a schedule item but there is a current event. We could: + * -> Reschedule the schedule item and let current event finish + * -> Kill the current event and run the scheduled item. + * -> Disable schedule timer while in an event; could cause us to be late. + * -> Wait for current event to finish hoping it does before schedule item. + */ + +/* Queue for timers */ +TAILQ_HEAD(ll_sched_qhead, ble_ll_sched_item) g_ble_ll_sched_q; + +#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING) +struct ble_ll_sched_obj g_ble_ll_sched_data; +#endif + +/** + * Checks if two events in the schedule will overlap in time. NOTE: consecutive + * schedule items can end and start at the same time. + * + * @param s1 + * @param s2 + * + * @return int 0: dont overlap 1:overlap + */ +static int +ble_ll_sched_is_overlap(struct ble_ll_sched_item *s1, + struct ble_ll_sched_item *s2) +{ + int rc; + + rc = 1; + if ((int32_t)(s1->start_time - s2->start_time) < 0) { + /* Make sure this event does not overlap current event */ + if ((int32_t)(s1->end_time - s2->start_time) <= 0) { + rc = 0; + } + } else { + /* Check for overlap */ + if ((int32_t)(s1->start_time - s2->end_time) >= 0) { + rc = 0; + } + } + + return rc; +} + +/* + * Determines if the schedule item overlaps the currently running schedule + * item. We only care about connection schedule items + */ +static int +ble_ll_sched_overlaps_current(struct ble_ll_sched_item *sch) +{ + int rc; + uint32_t ce_end_time; + + rc = 0; + if (ble_ll_state_get() == BLE_LL_STATE_CONNECTION) { + ce_end_time = ble_ll_conn_get_ce_end_time(); + if ((int32_t)(ce_end_time - sch->start_time) > 0) { + rc = 1; + } + } + return rc; +} + +static int +ble_ll_sched_conn_overlap(struct ble_ll_sched_item *entry) +{ + int rc; + struct ble_ll_conn_sm *connsm; + + /* Should only be advertising or a connection here */ + if (entry->sched_type == BLE_LL_SCHED_TYPE_CONN) { + connsm = (struct ble_ll_conn_sm *)entry->cb_arg; + entry->enqueued = 0; + TAILQ_REMOVE(&g_ble_ll_sched_q, entry, link); + ble_ll_event_send(&connsm->conn_ev_end); + rc = 0; + } else { + rc = -1; + } + + return rc; +} + +static struct ble_ll_sched_item * +ble_ll_sched_insert_if_empty(struct ble_ll_sched_item *sch) +{ + struct ble_ll_sched_item *entry; + + entry = TAILQ_FIRST(&g_ble_ll_sched_q); + if (!entry) { + TAILQ_INSERT_HEAD(&g_ble_ll_sched_q, sch, link); + sch->enqueued = 1; + } + return entry; +} + +int +ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm) +{ + int rc; + os_sr_t sr; + uint32_t usecs; + struct ble_ll_sched_item *sch; + struct ble_ll_sched_item *start_overlap; + struct ble_ll_sched_item *end_overlap; + struct ble_ll_sched_item *entry; + struct ble_ll_conn_sm *tmp; + + /* Get schedule element from connection */ + sch = &connsm->conn_sch; + + /* Set schedule start and end times */ + sch->start_time = connsm->anchor_point - g_ble_ll_sched_offset_ticks; + if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { + usecs = connsm->slave_cur_window_widening; + sch->start_time -= (os_cputime_usecs_to_ticks(usecs) + 1); + sch->remainder = 0; + } else { + sch->remainder = connsm->anchor_point_usecs; + } + sch->end_time = connsm->ce_end_time; + + /* Better be past current time or we just leave */ + if ((int32_t)(sch->start_time - os_cputime_get32()) < 0) { + return -1; + } + + /* We have to find a place for this schedule */ + OS_ENTER_CRITICAL(sr); + + if (ble_ll_sched_overlaps_current(sch)) { + OS_EXIT_CRITICAL(sr); + return -1; + } + + /* Stop timer since we will add an element */ + os_cputime_timer_stop(&g_ble_ll_sched_timer); + + start_overlap = NULL; + end_overlap = NULL; + rc = 0; + TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { + if (ble_ll_sched_is_overlap(sch, entry)) { + if (entry->sched_type == BLE_LL_SCHED_TYPE_CONN && + !ble_ll_conn_is_lru((struct ble_ll_conn_sm *)sch->cb_arg, + (struct ble_ll_conn_sm *)entry->cb_arg)) { + /* Only insert if this element is older than all that we + * overlap + */ + start_overlap = NULL; + rc = -1; + break; + } + + if (start_overlap == NULL) { + start_overlap = entry; + end_overlap = entry; + } else { + end_overlap = entry; + } + } else { + if ((int32_t)(sch->end_time - entry->start_time) <= 0) { + rc = 0; + TAILQ_INSERT_BEFORE(entry, sch, link); + break; + } + } + } + + if (!rc) { + if (!entry) { + TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); + } + sch->enqueued = 1; + } + + /* Remove first to last scheduled elements */ + entry = start_overlap; + while (entry) { + start_overlap = TAILQ_NEXT(entry,link); + switch (entry->sched_type) { + case BLE_LL_SCHED_TYPE_CONN: + tmp = (struct ble_ll_conn_sm *)entry->cb_arg; + ble_ll_event_send(&tmp->conn_ev_end); + break; + case BLE_LL_SCHED_TYPE_ADV: + ble_ll_adv_event_rmvd_from_sched((struct ble_ll_adv_sm *)entry->cb_arg); + break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + case BLE_LL_SCHED_TYPE_AUX_SCAN: + ble_ll_scan_end_adv_evt((struct ble_ll_aux_data *)entry->cb_arg); + break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + case BLE_LL_SCHED_TYPE_PERIODIC: + ble_ll_adv_periodic_rmvd_from_sched((struct ble_ll_adv_sm *)entry->cb_arg); + break; + case BLE_LL_SCHED_TYPE_SYNC: + ble_ll_sync_rmvd_from_sched((struct ble_ll_sync_sm *)entry->cb_arg); + break; +#endif +#endif + default: + BLE_LL_ASSERT(0); + break; + } + + TAILQ_REMOVE(&g_ble_ll_sched_q, entry, link); + entry->enqueued = 0; + + if (entry == end_overlap) { + break; + } + entry = start_overlap; + } + + entry = TAILQ_FIRST(&g_ble_ll_sched_q); + if (entry == sch) { + ble_ll_rfmgmt_sched_changed(sch); + } else { + sch = entry; + } + + OS_EXIT_CRITICAL(sr); + + /* Restart timer */ + BLE_LL_ASSERT(sch != NULL); + os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); + + return rc; +} + +/** + * Called to schedule a connection when the current role is master. + * + * Context: Interrupt + * + * @param connsm + * @param ble_hdr + * @param pyld_len + * + * @return int + */ +#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING) +int +ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm, + struct ble_mbuf_hdr *ble_hdr, uint8_t pyld_len) +{ + int rc; + os_sr_t sr; + uint32_t initial_start; + uint32_t earliest_start; + uint32_t earliest_end; + uint32_t dur; + uint32_t itvl_t; + uint32_t adv_rxend; + int i; + uint32_t tpp; + uint32_t tse; + uint32_t np; + uint32_t cp; + uint32_t tick_in_period; + + struct ble_ll_sched_item *entry; + struct ble_ll_sched_item *sch; + + /* Better have a connsm */ + BLE_LL_ASSERT(connsm != NULL); + + /* Get schedule element from connection */ + rc = -1; + sch = &connsm->conn_sch; + + /* XXX: + * The calculations for the 32kHz crystal bear alot of explanation. The + * earliest possible time that the master can start the connection with a + * slave is 1.25 msecs from the end of the connection request. The + * connection request is sent an IFS time from the end of the advertising + * packet that was received plus the time it takes to send the connection + * request. At 1 Mbps, this is 1752 usecs, or 57.41 ticks. Using 57 ticks + * makes us off ~13 usecs. Since we dont want to actually calculate the + * receive end time tick (this would take too long), we assume the end of + * the advertising PDU is 'now' (we call os_cputime_get32). We dont know + * how much time it will take to service the ISR but if we are more than the + * rx to tx time of the chip we will not be successful transmitting the + * connect request. All this means is that we presume that the slave will + * receive the connect request later than we expect but no earlier than + * 13 usecs before (this is important). + * + * The code then attempts to schedule the connection at the + * earliest time although this may not be possible. When the actual + * schedule start time is determined, the master has to determine if this + * time is more than a transmit window offset interval (1.25 msecs). The + * master has to tell the slave how many transmit window offsets there are + * from the earliest possible time to when the actual transmit start will + * occur. Later in this function you will see the calculation. The actual + * transmission start has to occur within the transmit window. The transmit + * window interval is in units of 1.25 msecs and has to be at least 1. To + * make things a bit easier (but less power efficient for the slave), we + * use a transmit window of 2. We do this because we dont quite know the + * exact start of the transmission and if we are too early or too late we + * could miss the transmit window. A final note: the actual transmission + * start (the anchor point) is sched offset ticks from the schedule start + * time. We dont add this to the calculation when calculating the window + * offset. The reason we dont do this is we want to insure we transmit + * after the window offset we tell the slave. For example, say we think + * we are transmitting 1253 usecs from the earliest start. This would cause + * us to send a transmit window offset of 1. Since we are actually + * transmitting earlier than the slave thinks we could end up transmitting + * before the window offset. Transmitting later is fine since we have the + * transmit window to do so. Transmitting before is bad, since the slave + * wont be listening. We could do better calculation if we wanted to use + * a transmit window of 1 as opposed to 2, but for now we dont care. + */ + dur = os_cputime_usecs_to_ticks(g_ble_ll_sched_data.sch_ticks_per_period); + adv_rxend = os_cputime_get32(); + if (ble_hdr->rxinfo.channel >= BLE_PHY_NUM_DATA_CHANS) { + /* + * We received packet on advertising channel which means this is a legacy + * PDU on 1 Mbps - we do as described above. + */ + earliest_start = adv_rxend + 57; + } else { + /* + * The calculations are similar as above. + * + * We received packet on data channel which means this is AUX_ADV_IND + * received on secondary adv channel. We can schedule first packet at + * the earliest after "T_IFS + AUX_CONNECT_REQ + transmitWindowDelay". + * AUX_CONNECT_REQ and transmitWindowDelay times vary depending on which + * PHY we received on. + * + */ + if (ble_hdr->rxinfo.phy == BLE_PHY_1M) { + // 150 + 352 + 2500 = 3002us = 98.37 ticks + earliest_start = adv_rxend + 98; + } else if (ble_hdr->rxinfo.phy == BLE_PHY_2M) { + // 150 + 180 + 2500 = 2830us = 92.73 ticks + earliest_start = adv_rxend + 93; + } else if (ble_hdr->rxinfo.phy == BLE_PHY_CODED) { + // 150 + 2896 + 3750 = 6796us = 222.69 ticks + earliest_start = adv_rxend + 223; + } else { + BLE_LL_ASSERT(0); + } + } + earliest_start += MYNEWT_VAL(BLE_LL_CONN_INIT_MIN_WIN_OFFSET) * + BLE_LL_SCHED_32KHZ_TICKS_PER_SLOT; + itvl_t = connsm->conn_itvl_ticks; + + /* We have to find a place for this schedule */ + OS_ENTER_CRITICAL(sr); + + /* + * Are there any allocated periods? If not, set epoch start to earliest + * time + */ + if (g_ble_ll_sched_data.sch_num_occ_periods == 0) { + g_ble_ll_sched_data.sch_epoch_start = earliest_start; + cp = 0; + } else { + /* + * Earliest start must occur on period boundary. + * (tse = ticks since epoch) + */ + tpp = g_ble_ll_sched_data.sch_ticks_per_period; + tse = earliest_start - g_ble_ll_sched_data.sch_epoch_start; + np = tse / tpp; + cp = np % BLE_LL_SCHED_PERIODS; + tick_in_period = tse - (np * tpp); + if (tick_in_period != 0) { + ++cp; + if (cp == BLE_LL_SCHED_PERIODS) { + cp = 0; + } + earliest_start += (tpp - tick_in_period); + } + + /* Now find first un-occupied period starting from cp */ + for (i = 0; i < BLE_LL_SCHED_PERIODS; ++i) { + if (g_ble_ll_sched_data.sch_occ_period_mask & (1 << cp)) { + ++cp; + if (cp == BLE_LL_SCHED_PERIODS) { + cp = 0; + } + earliest_start += tpp; + } else { + /* not occupied */ + break; + } + } + /* Should never happen but if it does... */ + if (i == BLE_LL_SCHED_PERIODS) { + OS_EXIT_CRITICAL(sr); + return rc; + } + } + + sch->start_time = earliest_start; + initial_start = earliest_start; + earliest_end = earliest_start + dur; + + if (!ble_ll_sched_insert_if_empty(sch)) { + /* Nothing in schedule. Schedule as soon as possible */ + rc = 0; + connsm->tx_win_off = MYNEWT_VAL(BLE_LL_CONN_INIT_MIN_WIN_OFFSET); + } else { + os_cputime_timer_stop(&g_ble_ll_sched_timer); + TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { + /* Set these because overlap function needs them to be set */ + sch->start_time = earliest_start; + sch->end_time = earliest_end; + + /* We can insert if before entry in list */ + if ((int32_t)(sch->end_time - entry->start_time) <= 0) { + if ((earliest_start - initial_start) <= itvl_t) { + rc = 0; + TAILQ_INSERT_BEFORE(entry, sch, link); + } + break; + } + + /* Check for overlapping events */ + if (ble_ll_sched_is_overlap(sch, entry)) { + /* Earliest start is end of this event since we overlap */ + earliest_start = entry->end_time; + earliest_end = earliest_start + dur; + } + } + + /* Must be able to schedule within one connection interval */ + if (!entry) { + if ((earliest_start - initial_start) <= itvl_t) { + rc = 0; + TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); + } + } + + if (!rc) { + /* calculate number of window offsets. Each offset is 1.25 ms */ + sch->enqueued = 1; + /* + * NOTE: we dont add sched offset ticks as we want to under-estimate + * the transmit window slightly since the window size is currently + * 2 when using a 32768 crystal. + */ + dur = os_cputime_ticks_to_usecs(earliest_start - initial_start); + connsm->tx_win_off = dur / BLE_LL_CONN_TX_OFF_USECS; + } + } + + if (!rc) { + sch->start_time = earliest_start; + sch->end_time = earliest_end; + /* + * Since we have the transmit window to transmit in, we dont need + * to set the anchor point usecs; just transmit to the nearest tick. + */ + connsm->anchor_point = earliest_start + g_ble_ll_sched_offset_ticks; + connsm->anchor_point_usecs = 0; + connsm->ce_end_time = earliest_end; + connsm->period_occ_mask = (1 << cp); + g_ble_ll_sched_data.sch_occ_period_mask |= connsm->period_occ_mask; + ++g_ble_ll_sched_data.sch_num_occ_periods; + } + + + /* Get head of list to restart timer */ + sch = TAILQ_FIRST(&g_ble_ll_sched_q); + ble_ll_rfmgmt_sched_changed(sch); + + OS_EXIT_CRITICAL(sr); + + os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); + + return rc; +} +#else +int +ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm, + struct ble_mbuf_hdr *ble_hdr, uint8_t pyld_len) +{ + int rc; + os_sr_t sr; + uint8_t req_slots; + uint32_t initial_start; + uint32_t earliest_start; + uint32_t earliest_end; + uint32_t dur; + uint32_t itvl_t; + uint32_t adv_rxend; + struct ble_ll_sched_item *entry; + struct ble_ll_sched_item *sch; + + /* + * XXX: TODO this code assumes the advertisement and connect request were + * sent at 1Mbps. + */ + + /* Get schedule element from connection */ + rc = -1; + sch = &connsm->conn_sch; + req_slots = MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS); + + /* XXX: + * The calculations for the 32kHz crystal bear alot of explanation. The + * earliest possible time that the master can start the connection with a + * slave is 1.25 msecs from the end of the connection request. The + * connection request is sent an IFS time from the end of the advertising + * packet that was received plus the time it takes to send the connection + * request. At 1 Mbps, this is 1752 usecs, or 57.41 ticks. Using 57 ticks + * makes us off ~13 usecs. Since we dont want to actually calculate the + * receive end time tick (this would take too long), we assume the end of + * the advertising PDU is 'now' (we call os_cputime_get32). We dont know + * how much time it will take to service the ISR but if we are more than the + * rx to tx time of the chip we will not be successful transmitting the + * connect request. All this means is that we presume that the slave will + * receive the connect request later than we expect but no earlier than + * 13 usecs before (this is important). + * + * The code then attempts to schedule the connection at the + * earliest time although this may not be possible. When the actual + * schedule start time is determined, the master has to determine if this + * time is more than a transmit window offset interval (1.25 msecs). The + * master has to tell the slave how many transmit window offsets there are + * from the earliest possible time to when the actual transmit start will + * occur. Later in this function you will see the calculation. The actual + * transmission start has to occur within the transmit window. The transmit + * window interval is in units of 1.25 msecs and has to be at least 1. To + * make things a bit easier (but less power efficient for the slave), we + * use a transmit window of 2. We do this because we dont quite know the + * exact start of the transmission and if we are too early or too late we + * could miss the transmit window. A final note: the actual transmission + * start (the anchor point) is sched offset ticks from the schedule start + * time. We dont add this to the calculation when calculating the window + * offset. The reason we dont do this is we want to insure we transmit + * after the window offset we tell the slave. For example, say we think + * we are transmitting 1253 usecs from the earliest start. This would cause + * us to send a transmit window offset of 1. Since we are actually + * transmitting earlier than the slave thinks we could end up transmitting + * before the window offset. Transmitting later is fine since we have the + * transmit window to do so. Transmitting before is bad, since the slave + * wont be listening. We could do better calculation if we wanted to use + * a transmit window of 1 as opposed to 2, but for now we dont care. + */ + dur = req_slots * BLE_LL_SCHED_32KHZ_TICKS_PER_SLOT; + adv_rxend = os_cputime_get32(); + if (ble_hdr->rxinfo.channel >= BLE_PHY_NUM_DATA_CHANS) { + /* + * We received packet on advertising channel which means this is a legacy + * PDU on 1 Mbps - we do as described above. + */ + earliest_start = adv_rxend + 57; + } else { + /* + * The calculations are similar as above. + * + * We received packet on data channel which means this is AUX_ADV_IND + * received on secondary adv channel. We can schedule first packet at + * the earliest after "T_IFS + AUX_CONNECT_REQ + transmitWindowDelay". + * AUX_CONNECT_REQ and transmitWindowDelay times vary depending on which + * PHY we received on. + * + */ + if (ble_hdr->rxinfo.phy == BLE_PHY_1M) { + // 150 + 352 + 2500 = 3002us = 98.37 ticks + earliest_start = adv_rxend + 98; + } else if (ble_hdr->rxinfo.phy == BLE_PHY_2M) { + // 150 + 180 + 2500 = 2830us = 92.73 ticks + earliest_start = adv_rxend + 93; + } else if (ble_hdr->rxinfo.phy == BLE_PHY_CODED) { + // 150 + 2896 + 3750 = 6796us = 222.69 ticks + earliest_start = adv_rxend + 223; + } else { + BLE_LL_ASSERT(0); + } + } + earliest_start += MYNEWT_VAL(BLE_LL_CONN_INIT_MIN_WIN_OFFSET) * + BLE_LL_SCHED_32KHZ_TICKS_PER_SLOT; + earliest_end = earliest_start + dur; + itvl_t = connsm->conn_itvl_ticks; + + /* We have to find a place for this schedule */ + OS_ENTER_CRITICAL(sr); + + /* The schedule item must occur after current running item (if any) */ + sch->start_time = earliest_start; + initial_start = earliest_start; + + if (!ble_ll_sched_insert_if_empty(sch)) { + /* Nothing in schedule. Schedule as soon as possible */ + rc = 0; + connsm->tx_win_off = MYNEWT_VAL(BLE_LL_CONN_INIT_MIN_WIN_OFFSET); + } else { + os_cputime_timer_stop(&g_ble_ll_sched_timer); + TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { + /* Set these because overlap function needs them to be set */ + sch->start_time = earliest_start; + sch->end_time = earliest_end; + + /* We can insert if before entry in list */ + if ((int32_t)(sch->end_time - entry->start_time) <= 0) { + if ((earliest_start - initial_start) <= itvl_t) { + rc = 0; + TAILQ_INSERT_BEFORE(entry, sch, link); + } + break; + } + + /* Check for overlapping events */ + if (ble_ll_sched_is_overlap(sch, entry)) { + /* Earliest start is end of this event since we overlap */ + earliest_start = entry->end_time; + earliest_end = earliest_start + dur; + } + } + + /* Must be able to schedule within one connection interval */ + if (!entry) { + if ((earliest_start - initial_start) <= itvl_t) { + rc = 0; + TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); + } + } + + if (!rc) { + /* calculate number of window offsets. Each offset is 1.25 ms */ + sch->enqueued = 1; + /* + * NOTE: we dont add sched offset ticks as we want to under-estimate + * the transmit window slightly since the window size is currently + * 2 when using a 32768 crystal. + */ + dur = os_cputime_ticks_to_usecs(earliest_start - initial_start); + connsm->tx_win_off = dur / BLE_LL_CONN_TX_OFF_USECS; + } + } + + if (!rc) { + sch->start_time = earliest_start; + sch->end_time = earliest_end; + /* + * Since we have the transmit window to transmit in, we dont need + * to set the anchor point usecs; just transmit to the nearest tick. + */ + connsm->anchor_point = earliest_start + g_ble_ll_sched_offset_ticks; + connsm->anchor_point_usecs = 0; + connsm->ce_end_time = earliest_end; + } + + /* Get head of list to restart timer */ + sch = TAILQ_FIRST(&g_ble_ll_sched_q); + ble_ll_rfmgmt_sched_changed(sch); + + OS_EXIT_CRITICAL(sr); + + os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); + + return rc; +} +#endif + +/** + * Schedules a slave connection for the first time. + * + * Context: Link Layer + * + * @param connsm + * + * @return int + */ +int +ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm) +{ + int rc; + os_sr_t sr; + struct ble_ll_sched_item *entry; + struct ble_ll_sched_item *next_sch; + struct ble_ll_sched_item *sch; + int first = 0; + + /* Get schedule element from connection */ + rc = -1; + sch = &connsm->conn_sch; + + /* Set schedule start and end times */ + /* + * XXX: for now, we dont care about anchor point usecs for the slave. It + * does not matter if we turn on the receiver up to one tick before w + * need to. We also subtract one extra tick since the conversion from + * usecs to ticks could be off by up to 1 tick. + */ + sch->start_time = connsm->anchor_point - g_ble_ll_sched_offset_ticks - + os_cputime_usecs_to_ticks(connsm->slave_cur_window_widening) - 1; + sch->end_time = connsm->ce_end_time; + sch->remainder = 0; + + /* We have to find a place for this schedule */ + OS_ENTER_CRITICAL(sr); + + /* The schedule item must occur after current running item (if any) */ + if (ble_ll_sched_overlaps_current(sch)) { + OS_EXIT_CRITICAL(sr); + return rc; + } + + entry = ble_ll_sched_insert_if_empty(sch); + if (!entry) { + /* Nothing in schedule. Schedule as soon as possible */ + rc = 0; + first = 1; + } else { + os_cputime_timer_stop(&g_ble_ll_sched_timer); + while (1) { + next_sch = entry->link.tqe_next; + /* Insert if event ends before next starts */ + if ((int32_t)(sch->end_time - entry->start_time) <= 0) { + rc = 0; + TAILQ_INSERT_BEFORE(entry, sch, link); + break; + } + + if (ble_ll_sched_is_overlap(sch, entry)) { + /* If we overlap with a connection, we re-schedule */ + if (ble_ll_sched_conn_overlap(entry)) { + break; + } + } + + /* Move to next entry */ + entry = next_sch; + + /* Insert at tail if none left to check */ + if (!entry) { + rc = 0; + TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); + break; + } + } + + if (!rc) { + sch->enqueued = 1; + } + + next_sch = TAILQ_FIRST(&g_ble_ll_sched_q); + if (next_sch == sch) { + first = 1; + } else { + sch = next_sch; + } + } + + if (first) { + ble_ll_rfmgmt_sched_changed(sch); + } + + OS_EXIT_CRITICAL(sr); + + os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); + + return rc; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) +/* + * Determines if the schedule item overlaps the currently running schedule + * item. This function cares about connection and sync. + */ +static int +ble_ll_sched_sync_overlaps_current(struct ble_ll_sched_item *sch) +{ + uint32_t end_time; + uint8_t state; + + state = ble_ll_state_get(); + switch (state) { + case BLE_LL_STATE_CONNECTION: + end_time = ble_ll_conn_get_ce_end_time(); + break; + case BLE_LL_STATE_SYNC: + end_time = ble_ll_sync_get_event_end_time(); + break; + default: + return 0; + } + + return CPUTIME_GT(end_time, sch->start_time); +} + +int +ble_ll_sched_sync_reschedule(struct ble_ll_sched_item *sch, + uint32_t anchor_point, uint8_t anchor_point_usecs, + uint32_t window_widening, + int8_t phy_mode) +{ + struct ble_ll_sched_item *entry; + uint8_t start_time_rem_usecs; + uint8_t window_rem_usecs; + uint32_t window_ticks; + uint32_t start_time; + uint32_t end_time; + uint32_t dur; + int rc = 0; + os_sr_t sr; + + window_ticks = os_cputime_usecs_to_ticks(window_widening); + window_rem_usecs = window_widening - os_cputime_ticks_to_usecs(window_ticks); + + /* adjust for subtraction */ + anchor_point_usecs += 31; + anchor_point--; + + start_time = anchor_point - window_ticks; + start_time_rem_usecs = anchor_point_usecs - window_rem_usecs; + if (start_time_rem_usecs >= 31) { + start_time++; + start_time_rem_usecs -= 31; + } + + dur = ble_ll_pdu_tx_time_get(MYNEWT_VAL(BLE_LL_SCHED_SCAN_SYNC_PDU_LEN), + phy_mode); + end_time = start_time + os_cputime_usecs_to_ticks(dur); + + start_time -= g_ble_ll_sched_offset_ticks; + + /* Set schedule start and end times */ + sch->start_time = start_time; + sch->remainder = start_time_rem_usecs; + sch->end_time = end_time; + + /* Better be past current time or we just leave */ + if (CPUTIME_LEQ(sch->start_time, os_cputime_get32())) { + return -1; + } + + /* We have to find a place for this schedule */ + OS_ENTER_CRITICAL(sr); + + if (ble_ll_sched_sync_overlaps_current(sch)) { + OS_EXIT_CRITICAL(sr); + return -1; + } + + /* Try to find slot for sync scan. */ + os_cputime_timer_stop(&g_ble_ll_sched_timer); + + TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { + /* We can insert if before entry in list */ + if (CPUTIME_LEQ(sch->end_time, entry->start_time)) { + TAILQ_INSERT_BEFORE(entry, sch, link); + sch->enqueued = 1; + break; + } + + /* Check for overlapping events. For now drop if it overlaps with + * anything. We can make it smarter later on + */ + if (ble_ll_sched_is_overlap(sch, entry)) { + rc = -1; + break; + } + } + + if (!entry) { + TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); + sch->enqueued = 1; + } + + entry = TAILQ_FIRST(&g_ble_ll_sched_q); + if (entry == sch) { + ble_ll_rfmgmt_sched_changed(sch); + } else { + sch = entry; + } + + OS_EXIT_CRITICAL(sr); + + /* Restart timer */ + BLE_LL_ASSERT(sch != NULL); + os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); + + return rc; +} + +int +ble_ll_sched_sync(struct ble_ll_sched_item *sch, + uint32_t beg_cputime, uint32_t rem_usecs, + uint32_t offset, int8_t phy_mode) +{ + struct ble_ll_sched_item *entry; + uint32_t start_time_rem_usecs; + uint32_t off_rem_usecs; + uint32_t start_time; + uint32_t off_ticks; + uint32_t end_time; + uint32_t dur; + os_sr_t sr; + int rc = 0; + + off_ticks = os_cputime_usecs_to_ticks(offset); + off_rem_usecs = offset - os_cputime_ticks_to_usecs(off_ticks); + + start_time = beg_cputime + off_ticks; + start_time_rem_usecs = rem_usecs + off_rem_usecs; + if (start_time_rem_usecs >= 31) { + start_time++; + start_time_rem_usecs -= 31; + } + + dur = ble_ll_pdu_tx_time_get(MYNEWT_VAL(BLE_LL_SCHED_SCAN_SYNC_PDU_LEN), + phy_mode); + end_time = start_time + os_cputime_usecs_to_ticks(dur); + + start_time -= g_ble_ll_sched_offset_ticks; + + sch->start_time = start_time; + sch->remainder = start_time_rem_usecs; + sch->end_time = end_time; + + OS_ENTER_CRITICAL(sr); + + if (!ble_ll_sched_insert_if_empty(sch)) { + /* Nothing in schedule. Schedule as soon as possible + * If we are here it means sch has been added to the scheduler */ + goto done; + } + + /* Try to find slot for scan. */ + os_cputime_timer_stop(&g_ble_ll_sched_timer); + TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { + /* We can insert if before entry in list */ + if (CPUTIME_LEQ(sch->end_time, entry->start_time)) { + TAILQ_INSERT_BEFORE(entry, sch, link); + sch->enqueued = 1; + break; + } + + /* Check for overlapping events. For now drop if it overlaps with + * anything. We can make it smarter later on + */ + if (ble_ll_sched_is_overlap(sch, entry)) { + rc = -1; + break; + } + } + + if (!entry) { + TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); + sch->enqueued = 1; + } + +done: + entry = TAILQ_FIRST(&g_ble_ll_sched_q); + if (entry == sch) { + ble_ll_rfmgmt_sched_changed(sch); + } else { + sch = entry; + } + + OS_EXIT_CRITICAL(sr); + + /* Restart timer */ + BLE_LL_ASSERT(sch != NULL); + os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); + + STATS_INC(ble_ll_stats, sync_scheduled); + return rc; +} +#endif + +int +ble_ll_sched_adv_new(struct ble_ll_sched_item *sch, ble_ll_sched_adv_new_cb cb, + void *arg) +{ + os_sr_t sr; + uint32_t adv_start; + uint32_t duration; + struct ble_ll_sched_item *entry; + struct ble_ll_sched_item *orig; + + /* Get length of schedule item */ + duration = sch->end_time - sch->start_time; + orig = sch; + + OS_ENTER_CRITICAL(sr); + entry = ble_ll_sched_insert_if_empty(sch); + if (!entry) { + adv_start = sch->start_time; + } else { + /* XXX: no need to stop timer if not first on list. Modify code? */ + os_cputime_timer_stop(&g_ble_ll_sched_timer); + TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { + /* We can insert if before entry in list */ + if ((int32_t)(sch->end_time - entry->start_time) <= 0) { + TAILQ_INSERT_BEFORE(entry, sch, link); + break; + } + + /* Check for overlapping events */ + if (ble_ll_sched_is_overlap(sch, entry)) { + /* Earliest start is end of this event since we overlap */ + sch->start_time = entry->end_time; + sch->end_time = sch->start_time + duration; + } + } + + if (!entry) { + TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); + } + adv_start = sch->start_time; + + sch->enqueued = 1; + + /* Restart with head of list */ + sch = TAILQ_FIRST(&g_ble_ll_sched_q); + } + + if (cb) { + cb((struct ble_ll_adv_sm *)orig->cb_arg, adv_start, arg); + } + + if (orig == sch) { + ble_ll_rfmgmt_sched_changed(sch); + } + + OS_EXIT_CRITICAL(sr); + + /* Restart timer */ + BLE_LL_ASSERT(sch != NULL); + os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); + + return 0; +} + +int +ble_ll_sched_periodic_adv(struct ble_ll_sched_item *sch, uint32_t *start, + bool after_overlap) +{ + int rc = 0; + os_sr_t sr; + uint32_t adv_start; + uint32_t duration; + struct ble_ll_sched_item *entry; + struct ble_ll_sched_item *orig = sch; + + /* Get length of schedule item */ + duration = sch->end_time - sch->start_time; + + OS_ENTER_CRITICAL(sr); + entry = ble_ll_sched_insert_if_empty(sch); + if (!entry) { + adv_start = sch->start_time; + } else { + /* XXX: no need to stop timer if not first on list. Modify code? */ + os_cputime_timer_stop(&g_ble_ll_sched_timer); + TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { + /* We can insert if before entry in list */ + if ((int32_t)(sch->end_time - entry->start_time) <= 0) { + TAILQ_INSERT_BEFORE(entry, sch, link); + break; + } + + /* Check for overlapping events */ + if (ble_ll_sched_is_overlap(sch, entry)) { + if (after_overlap) { + /* Earliest start is end of this event since we overlap */ + sch->start_time = entry->end_time; + sch->end_time = sch->start_time + duration; + } else { + rc = -1; + break; + } + } + } + + if (!entry) { + TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); + } + adv_start = sch->start_time; + + if (!rc) { + sch->enqueued = 1; + } + + /* Restart with head of list */ + sch = TAILQ_FIRST(&g_ble_ll_sched_q); + } + + if (!rc) { + *start = adv_start; + } + + if (orig == sch) { + ble_ll_rfmgmt_sched_changed(sch); + } + + OS_EXIT_CRITICAL(sr); + + /* Restart timer */ + BLE_LL_ASSERT(sch != NULL); + os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); + + return rc; +} + +int +ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t *start, + uint32_t max_delay_ticks) +{ + int rc; + os_sr_t sr; + uint32_t orig_start; + uint32_t duration; + uint32_t rand_ticks; + struct ble_ll_sched_item *entry; + struct ble_ll_sched_item *next_sch; + struct ble_ll_sched_item *before; + struct ble_ll_sched_item *start_overlap; + struct ble_ll_sched_item *end_overlap; + + /* Get length of schedule item */ + duration = sch->end_time - sch->start_time; + + /* Add maximum randomization delay to end */ + rand_ticks = max_delay_ticks; + sch->end_time += max_delay_ticks; + + start_overlap = NULL; + end_overlap = NULL; + before = NULL; + rc = 0; + OS_ENTER_CRITICAL(sr); + + entry = ble_ll_sched_insert_if_empty(sch); + if (entry) { + os_cputime_timer_stop(&g_ble_ll_sched_timer); + while (1) { + next_sch = entry->link.tqe_next; + if (ble_ll_sched_is_overlap(sch, entry)) { + if (start_overlap == NULL) { + start_overlap = entry; + end_overlap = entry; + } else { + end_overlap = entry; + } + } else { + if ((int32_t)(sch->end_time - entry->start_time) <= 0) { + before = entry; + break; + } + } + + entry = next_sch; + if (entry == NULL) { + break; + } + } + + /* + * If there is no overlap, we either insert before the 'before' entry + * or we insert at the end if there is no before entry. + */ + if (start_overlap == NULL) { + if (before) { + TAILQ_INSERT_BEFORE(before, sch, link); + } else { + TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); + } + } else { + /* + * This item will overlap with others. See if we can fit it in + * with original duration. + */ + before = NULL; + orig_start = sch->start_time; + entry = start_overlap; + sch->end_time = sch->start_time + duration; + while (1) { + next_sch = entry->link.tqe_next; + if ((int32_t)(sch->end_time - entry->start_time) <= 0) { + rand_ticks = entry->start_time - sch->end_time; + before = entry; + TAILQ_INSERT_BEFORE(before, sch, link); + break; + } else { + sch->start_time = entry->end_time; + sch->end_time = sch->start_time + duration; + } + + if (entry == end_overlap) { + rand_ticks = (orig_start + max_delay_ticks) - sch->start_time; + if (rand_ticks > max_delay_ticks) { + /* No place for advertisement. */ + rc = -1; + } else { + if (next_sch == NULL) { + TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); + } else { + TAILQ_INSERT_BEFORE(next_sch, sch, link); + } + } + break; + } + entry = next_sch; + BLE_LL_ASSERT(entry != NULL); + } + } + } + + if (!rc) { + sch->enqueued = 1; + if (rand_ticks) { + sch->start_time += rand() % rand_ticks; + } + sch->end_time = sch->start_time + duration; + *start = sch->start_time; + + if (sch == TAILQ_FIRST(&g_ble_ll_sched_q)) { + ble_ll_rfmgmt_sched_changed(sch); + } + } + + OS_EXIT_CRITICAL(sr); + + sch = TAILQ_FIRST(&g_ble_ll_sched_q); + os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); + + return rc; +} + +int +ble_ll_sched_adv_resched_pdu(struct ble_ll_sched_item *sch) +{ + uint8_t lls; + os_sr_t sr; + struct ble_ll_sched_item *entry; + + OS_ENTER_CRITICAL(sr); + + lls = ble_ll_state_get(); + if ((lls == BLE_LL_STATE_ADV) || (lls == BLE_LL_STATE_CONNECTION) || + (lls == BLE_LL_STATE_SYNC)) { + goto adv_resched_pdu_fail; + } + + entry = ble_ll_sched_insert_if_empty(sch); + if (entry) { + /* If we overlap with the first item, simply re-schedule */ + if (ble_ll_sched_is_overlap(sch, entry)) { + goto adv_resched_pdu_fail; + } + os_cputime_timer_stop(&g_ble_ll_sched_timer); + TAILQ_INSERT_BEFORE(entry, sch, link); + sch->enqueued = 1; + } + + ble_ll_rfmgmt_sched_changed(TAILQ_FIRST(&g_ble_ll_sched_q)); + + OS_EXIT_CRITICAL(sr); + os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); + return 0; + +adv_resched_pdu_fail: + OS_EXIT_CRITICAL(sr); + return -1; +} + +/** + * Remove a schedule element + * + * @param sched_type + * + * @return int 0 - removed, 1 - not in the list + */ +int +ble_ll_sched_rmv_elem(struct ble_ll_sched_item *sch) +{ + os_sr_t sr; + struct ble_ll_sched_item *first; + int rc = 1; + + if (!sch) { + return rc; + } + + OS_ENTER_CRITICAL(sr); + if (sch->enqueued) { + first = TAILQ_FIRST(&g_ble_ll_sched_q); + if (first == sch) { + os_cputime_timer_stop(&g_ble_ll_sched_timer); + } + + TAILQ_REMOVE(&g_ble_ll_sched_q, sch, link); + sch->enqueued = 0; + rc = 0; + + if (first == sch) { + first = TAILQ_FIRST(&g_ble_ll_sched_q); + if (first) { + os_cputime_timer_start(&g_ble_ll_sched_timer, first->start_time); + } + ble_ll_rfmgmt_sched_changed(first); + } + } + OS_EXIT_CRITICAL(sr); + + return rc; +} + +void +ble_ll_sched_rmv_elem_type(uint8_t type, sched_remove_cb_func remove_cb) +{ + os_sr_t sr; + struct ble_ll_sched_item *entry; + struct ble_ll_sched_item *first; + + OS_ENTER_CRITICAL(sr); + first = TAILQ_FIRST(&g_ble_ll_sched_q); + + if (!first) { + OS_EXIT_CRITICAL(sr); + return; + } + + TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { + if (entry->sched_type == type) { + if (first == entry) { + os_cputime_timer_stop(&g_ble_ll_sched_timer); + first = NULL; + } + + TAILQ_REMOVE(&g_ble_ll_sched_q, entry, link); + remove_cb(entry); + entry->enqueued = 0; + } + } + + if (!first) { + first = TAILQ_FIRST(&g_ble_ll_sched_q); + if (first) { + os_cputime_timer_start(&g_ble_ll_sched_timer, first->start_time); + } + ble_ll_rfmgmt_sched_changed(first); + } + + OS_EXIT_CRITICAL(sr); +} + +/** + * Executes a schedule item by calling the schedule callback function. + * + * Context: Interrupt + * + * @param sch Pointer to schedule item + * + * @return int 0: schedule item is not over; otherwise schedule item is done. + */ +static int +ble_ll_sched_execute_item(struct ble_ll_sched_item *sch) +{ + int rc; + uint8_t lls; + + lls = ble_ll_state_get(); + + ble_ll_trace_u32x3(BLE_LL_TRACE_ID_SCHED, lls, os_cputime_get32(), + sch->start_time); + + if (lls == BLE_LL_STATE_STANDBY) { + goto sched; + } + + /* If aux scan scheduled and LL is in state when scanner is running + * in 3 states: + * BLE_LL_STATE_SCANNING + * BLE_LL_STATE_INITIATING + * BLE_LL_STATE_STANDBY + * + * Let scanner to decide to disable phy or not. + */ + if (sch->sched_type == BLE_LL_SCHED_TYPE_AUX_SCAN) { + if (lls == BLE_LL_STATE_INITIATING || lls == BLE_LL_STATE_SCANNING) { + goto sched; + } + } + + /* + * This is either an advertising event or connection event start. If + * we are scanning or initiating just stop it. + */ + + /* We have to disable the PHY no matter what */ + ble_phy_disable(); + + if (lls == BLE_LL_STATE_SCANNING) { + ble_ll_state_set(BLE_LL_STATE_STANDBY); + ble_ll_scan_halt(); + } else if (lls == BLE_LL_STATE_INITIATING) { + ble_ll_state_set(BLE_LL_STATE_STANDBY); + ble_ll_scan_halt(); + /* PHY is disabled - make sure we do not wait for AUX_CONNECT_RSP */ + ble_ll_conn_reset_pending_aux_conn_rsp(); + } else if (lls == BLE_LL_STATE_ADV) { + STATS_INC(ble_ll_stats, sched_state_adv_errs); + ble_ll_adv_halt(); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + } else if (lls == BLE_LL_STATE_SYNC) { + STATS_INC(ble_ll_stats, sched_state_sync_errs); + ble_ll_sync_halt(); +#endif + } else { + STATS_INC(ble_ll_stats, sched_state_conn_errs); + ble_ll_conn_event_halt(); + } + +sched: + BLE_LL_DEBUG_GPIO(SCHED_ITEM_CB, 1); + BLE_LL_ASSERT(sch->sched_cb); + rc = sch->sched_cb(sch); + BLE_LL_DEBUG_GPIO(SCHED_ITEM_CB, 0); + return rc; +} + +/** + * Run the BLE scheduler. Iterate through all items on the schedule queue. + * + * Context: interrupt (scheduler) + * + * @return int + */ +static void +ble_ll_sched_run(void *arg) +{ + struct ble_ll_sched_item *sch; + + BLE_LL_DEBUG_GPIO(SCHED_RUN, 1); + + /* Look through schedule queue */ + sch = TAILQ_FIRST(&g_ble_ll_sched_q); + if (sch) { +#if (BLE_LL_SCHED_DEBUG == 1) + int32_t dt; + + /* Make sure we have passed the start time of the first event */ + dt = (int32_t)(os_cputime_get32() - sch->start_time); + if (dt > g_ble_ll_sched_max_late) { + g_ble_ll_sched_max_late = dt; + } + if (dt < g_ble_ll_sched_max_early) { + g_ble_ll_sched_max_early = dt; + } +#endif + + /* Remove schedule item and execute the callback */ + TAILQ_REMOVE(&g_ble_ll_sched_q, sch, link); + sch->enqueued = 0; + ble_ll_sched_execute_item(sch); + + /* Restart if there is an item on the schedule */ + sch = TAILQ_FIRST(&g_ble_ll_sched_q); + if (sch) { + os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); + } + ble_ll_rfmgmt_sched_changed(sch); + } + + BLE_LL_DEBUG_GPIO(SCHED_RUN, 0); +} + +/** + * Called to determine when the next scheduled event will occur. + * + * If there are not scheduled events this function returns 0; otherwise it + * returns 1 and *next_event_time is set to the start time of the next event. + * + * @param next_event_time + * + * @return int 0: No events are scheduled 1: there is an upcoming event + */ +int +ble_ll_sched_next_time(uint32_t *next_event_time) +{ + int rc; + os_sr_t sr; + struct ble_ll_sched_item *first; + + rc = 0; + OS_ENTER_CRITICAL(sr); + first = TAILQ_FIRST(&g_ble_ll_sched_q); + if (first) { + *next_event_time = first->start_time; + rc = 1; + } + OS_EXIT_CRITICAL(sr); + + return rc; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +/** + * Called to check if there is place for a planned scan req. + * + * @param chan + * @param phy_mode + * + * @return int 0: Clear for scan req 1: there is an upcoming event + */ +int +ble_ll_sched_scan_req_over_aux_ptr(uint32_t chan, uint8_t phy_mode) +{ + struct ble_ll_sched_item *sch; + uint32_t usec_dur; + uint32_t now = os_cputime_get32(); + + /* Lets calculate roughly how much time we need for scan req and scan rsp */ + usec_dur = ble_ll_pdu_tx_time_get(BLE_SCAN_REQ_LEN, phy_mode); + if (chan >= BLE_PHY_NUM_DATA_CHANS) { + usec_dur += ble_ll_pdu_tx_time_get(BLE_SCAN_RSP_MAX_LEN, phy_mode); + } else { + usec_dur += ble_ll_pdu_tx_time_get(BLE_SCAN_RSP_MAX_EXT_LEN, phy_mode); + } + + sch = TAILQ_FIRST(&g_ble_ll_sched_q); + while (sch) { + /* Let's check if there is no scheduled item which want to start within + * given usecs.*/ + if ((int32_t)(sch->start_time - now + os_cputime_usecs_to_ticks(usec_dur)) > 0) { + /* We are fine. Have time for scan req */ + return 0; + } + + /* There is something in the scheduler. If it is not aux ptr we assume + * it is more important that scan req + */ + if (sch->sched_type != BLE_LL_SCHED_TYPE_AUX_SCAN) { + return 1; + } + + ble_ll_scan_end_adv_evt((struct ble_ll_aux_data *)sch->cb_arg); + TAILQ_REMOVE(&g_ble_ll_sched_q, sch, link); + sch->enqueued = 0; + sch = TAILQ_FIRST(&g_ble_ll_sched_q); + } + return 0; +} + +/** + * Called to schedule a aux scan. + * + * Context: Interrupt + * + * @param ble_hdr + * @param scansm + * @param aux_scan + * + * @return 0 on success, 1 otherwise + */ +int +ble_ll_sched_aux_scan(struct ble_mbuf_hdr *ble_hdr, + struct ble_ll_scan_sm *scansm, + struct ble_ll_aux_data *aux_scan) +{ + int rc = 1; + os_sr_t sr; + uint32_t off_ticks; + uint32_t off_rem_usecs; + uint32_t start_time; + uint32_t start_time_rem_usecs; + uint32_t end_time; + uint32_t dur; + struct ble_ll_sched_item *entry; + struct ble_ll_sched_item *sch; + int phy_mode; + + sch = &aux_scan->sch; + BLE_LL_ASSERT(sch->cb_arg == NULL); + + off_ticks = os_cputime_usecs_to_ticks(aux_scan->offset); + off_rem_usecs = aux_scan->offset - os_cputime_ticks_to_usecs(off_ticks); + + start_time = ble_hdr->beg_cputime + off_ticks; + start_time_rem_usecs = ble_hdr->rem_usecs + off_rem_usecs; + if (start_time_rem_usecs >= 31) { + start_time++; + start_time_rem_usecs -= 31; + } + start_time -= g_ble_ll_sched_offset_ticks; + + /* Let's calculate time we reserve for aux packet. For now we assume to wait + * for fixed number of bytes and handle possible interrupting it in + * ble_ll_sched_execute_item(). This is because aux packet can be up to + * 256bytes and we don't want to block sched that long + */ + phy_mode = ble_ll_phy_to_phy_mode(aux_scan->aux_phy, + BLE_HCI_LE_PHY_CODED_ANY); + dur = ble_ll_pdu_tx_time_get(MYNEWT_VAL(BLE_LL_SCHED_SCAN_AUX_PDU_LEN), + phy_mode); + end_time = start_time + os_cputime_usecs_to_ticks(dur); + + sch->start_time = start_time; + sch->remainder = start_time_rem_usecs; + sch->end_time = end_time; + + OS_ENTER_CRITICAL(sr); + + if (!ble_ll_sched_insert_if_empty(sch)) { + /* Nothing in schedule. Schedule as soon as possible + * If we are here it means sch has been added to the scheduler */ + rc = 0; + goto done; + } + + /* Try to find slot for aux scan. */ + os_cputime_timer_stop(&g_ble_ll_sched_timer); + TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { + /* We can insert if before entry in list */ + if ((int32_t)(sch->end_time - entry->start_time) <= 0) { + rc = 0; + TAILQ_INSERT_BEFORE(entry, sch, link); + sch->enqueued = 1; + break; + } + + /* Check for overlapping events. For now drop if it overlaps with + * anything. We can make it smarter later on + */ + if (ble_ll_sched_is_overlap(sch, entry)) { + break; + } + } + + if (!entry) { + rc = 0; + TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); + sch->enqueued = 1; + } + +done: + + if (rc == 0) { + sch->cb_arg = ble_ll_scan_aux_data_ref(aux_scan); + STATS_INC(ble_ll_stats, aux_scheduled); + } + + /* Get head of list to restart timer */ + entry = TAILQ_FIRST(&g_ble_ll_sched_q); + if (entry == sch) { + ble_ll_rfmgmt_sched_changed(sch); + } else { + sch = entry; + } + + OS_EXIT_CRITICAL(sr); + + /* Restart timer */ + BLE_LL_ASSERT(sch != NULL); + os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); + + return rc; +} +#endif + +#if MYNEWT_VAL(BLE_LL_DTM) +int ble_ll_sched_dtm(struct ble_ll_sched_item *sch) +{ + int rc; + os_sr_t sr; + struct ble_ll_sched_item *entry; + + OS_ENTER_CRITICAL(sr); + + if (!ble_ll_sched_insert_if_empty(sch)) { + /* Nothing in schedule. Schedule as soon as possible + * If we are here it means sch has been added to the scheduler */ + rc = 0; + goto done; + } + + /* Try to find slot for test. */ + os_cputime_timer_stop(&g_ble_ll_sched_timer); + TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { + /* We can insert if before entry in list */ + if (sch->end_time <= entry->start_time) { + rc = 0; + TAILQ_INSERT_BEFORE(entry, sch, link); + sch->enqueued = 1; + break; + } + + /* Check for overlapping events. For now drop if it overlaps with + * anything. We can make it smarter later on + */ + if (ble_ll_sched_is_overlap(sch, entry)) { + OS_EXIT_CRITICAL(sr); + return -1; + } + } + + if (!entry) { + rc = 0; + TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); + sch->enqueued = 1; + } + +done: + + /* Get head of list to restart timer */ + sch = TAILQ_FIRST(&g_ble_ll_sched_q); + + ble_ll_rfmgmt_sched_changed(sch); + + OS_EXIT_CRITICAL(sr); + + /* Restart timer */ + BLE_LL_ASSERT(sch != NULL); + os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); + + return rc; +} +#endif +/** + * Stop the scheduler + * + * Context: Link Layer task + */ +void +ble_ll_sched_stop(void) +{ + os_cputime_timer_stop(&g_ble_ll_sched_timer); +} + +/** + * Initialize the scheduler. Should only be called once and should be called + * before any of the scheduler API are called. + * + * @return int + */ +int +ble_ll_sched_init(void) +{ + BLE_LL_DEBUG_GPIO_INIT(SCHED_ITEM_CB); + BLE_LL_DEBUG_GPIO_INIT(SCHED_RUN); + + /* + * Initialize max early to large negative number. This is used + * to determine the worst-case "early" time the schedule was called. Dont + * expect this to be less than -3 or -4. + */ +#if (BLE_LL_SCHED_DEBUG == 1) + g_ble_ll_sched_max_early = -50000; +#endif + + /* + * This is the offset from the start of the scheduled item until the actual + * tx/rx should occur, in ticks. We also "round up" to the nearest tick. + */ + g_ble_ll_sched_offset_ticks = + (uint8_t) os_cputime_usecs_to_ticks(XCVR_TX_SCHED_DELAY_USECS + 30); + + /* Initialize cputimer for the scheduler */ + os_cputime_timer_init(&g_ble_ll_sched_timer, ble_ll_sched_run, NULL); + +#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING) + memset(&g_ble_ll_sched_data, 0, sizeof(struct ble_ll_sched_obj)); + g_ble_ll_sched_data.sch_ticks_per_period = + os_cputime_usecs_to_ticks(MYNEWT_VAL(BLE_LL_USECS_PER_PERIOD)); + g_ble_ll_sched_data.sch_ticks_per_epoch = BLE_LL_SCHED_PERIODS * + g_ble_ll_sched_data.sch_ticks_per_period; +#endif + + return 0; +} + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_supp_cmd.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_supp_cmd.c new file mode 100644 index 000000000..6ee912fa3 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_supp_cmd.c @@ -0,0 +1,461 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef ESP_PLATFORM + +#include +#include + +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/include/nimble/nimble_opt.h" +#include "nimble/nimble/include/nimble/hci_common.h" +#include "../include/controller/ble_ll.h" +#include "../include/controller/ble_ll_hci.h" + +/* Octet 0 */ +#define BLE_SUPP_CMD_DISCONNECT (1 << 5) +#define BLE_LL_SUPP_CMD_OCTET_0 (BLE_SUPP_CMD_DISCONNECT) + +/* Octet 5 */ +#define BLE_SUPP_CMD_SET_EVENT_MASK (1 << 6) +#define BLE_LL_SUPP_CMD_OCTET_5 (BLE_SUPP_CMD_SET_EVENT_MASK) + +/* Octet 10 */ +#define BLE_SUPP_CMD_RD_TX_PWR (0 << 2) +#define BLE_LL_SUPP_CMD_OCTET_10 (BLE_SUPP_CMD_RD_TX_PWR) + +/* Octet 14 */ +#define BLE_SUPP_CMD_RD_LOC_VER (1 << 3) +#define BLE_SUPP_CMD_RD_LOC_SUPP_FEAT (1 << 5) +#define BLE_LL_SUPP_CMD_OCTET_14 \ +( \ + BLE_SUPP_CMD_RD_LOC_VER | \ + BLE_SUPP_CMD_RD_LOC_SUPP_FEAT \ +) + +/* Octet 15 */ +#define BLE_SUPP_CMD_RD_BD_ADDR (1 << 1) +#define BLE_SUPP_CMD_RD_RSSI (1 << 5) + +#define BLE_LL_SUPP_CMD_OCTET_15 \ +( \ + BLE_SUPP_CMD_RD_BD_ADDR | \ + BLE_SUPP_CMD_RD_RSSI \ +) + +/* Octet 25 */ +#define BLE_SUPP_CMD_LE_SET_EV_MASK (1 << 0) +#define BLE_SUPP_CMD_LE_RD_BUF_SIZE (1 << 1) +#define BLE_SUPP_CMD_LE_RD_LOC_FEAT (1 << 2) +#define BLE_SUPP_CMD_LE_SET_RAND_ADDR (1 << 4) +#define BLE_SUPP_CMD_LE_SET_ADV_PARAMS (1 << 5) +#define BLE_SUPP_CMD_LE_SET_ADV_TX_PWR (1 << 6) +#define BLE_SUPP_CMD_LE_SET_ADV_DATA (1 << 7) + +#define BLE_LL_SUPP_CMD_OCTET_25 \ +( \ + BLE_SUPP_CMD_LE_SET_EV_MASK | \ + BLE_SUPP_CMD_LE_RD_BUF_SIZE | \ + BLE_SUPP_CMD_LE_RD_LOC_FEAT | \ + BLE_SUPP_CMD_LE_SET_RAND_ADDR | \ + BLE_SUPP_CMD_LE_SET_ADV_PARAMS | \ + BLE_SUPP_CMD_LE_SET_ADV_TX_PWR | \ + BLE_SUPP_CMD_LE_SET_ADV_DATA \ +) + +/* Octet 26 */ +#define BLE_SUPP_CMD_LE_SET_SCAN_RSP_DATA (1 << 0) +#define BLE_SUPP_CMD_LE_SET_ADV_ENABLE (1 << 1) +#define BLE_SUPP_CMD_LE_SET_SCAN_PARAMS (1 << 2) +#define BLE_SUPP_CMD_LE_SET_SCAN_ENABLE (1 << 3) +#define BLE_SUPP_CMD_LE_CREATE_CONN (1 << 4) +#define BLE_SUPP_CMD_LE_CREATE_CONN_CANCEL (1 << 5) +#define BLE_SUPP_CMD_LE_RD_WHITELIST_SIZE (1 << 6) +#define BLE_SUPP_CMD_LE_CLR_WHITELIST (1 << 7) + +#define BLE_LL_SUPP_CMD_OCTET_26 \ +( \ + BLE_SUPP_CMD_LE_SET_SCAN_RSP_DATA | \ + BLE_SUPP_CMD_LE_SET_ADV_ENABLE | \ + BLE_SUPP_CMD_LE_SET_SCAN_PARAMS | \ + BLE_SUPP_CMD_LE_SET_SCAN_ENABLE | \ + BLE_SUPP_CMD_LE_CREATE_CONN | \ + BLE_SUPP_CMD_LE_CREATE_CONN_CANCEL | \ + BLE_SUPP_CMD_LE_RD_WHITELIST_SIZE | \ + BLE_SUPP_CMD_LE_CLR_WHITELIST \ +) + +/* Octet 27 */ +#define BLE_SUPP_CMD_LE_ADD_DEV_WHITELIST (1 << 0) +#define BLE_SUPP_CMD_LE_RMV_DEV_WHITELIST (1 << 1) +#define BLE_SUPP_CMD_LE_CONN_UPDATE (1 << 2) +#define BLE_SUPP_CMD_LE_SET_HOST_CHAN_CLASS (1 << 3) +#define BLE_SUPP_CMD_LE_RD_CHAN_MAP (1 << 4) +#define BLE_SUPP_CMD_LE_RD_REM_USED_FEAT (1 << 5) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) +#define BLE_SUPP_CMD_LE_ENCRYPT (1 << 6) +#else +#define BLE_SUPP_CMD_LE_ENCRYPT (0 << 6) +#endif +#define BLE_SUPP_CMD_LE_RAND (1 << 7) + +#define BLE_LL_SUPP_CMD_OCTET_27 \ +( \ + BLE_SUPP_CMD_LE_ENCRYPT | \ + BLE_SUPP_CMD_LE_RAND | \ + BLE_SUPP_CMD_LE_ADD_DEV_WHITELIST | \ + BLE_SUPP_CMD_LE_RMV_DEV_WHITELIST | \ + BLE_SUPP_CMD_LE_CONN_UPDATE | \ + BLE_SUPP_CMD_LE_SET_HOST_CHAN_CLASS | \ + BLE_SUPP_CMD_LE_RD_CHAN_MAP | \ + BLE_SUPP_CMD_LE_RD_REM_USED_FEAT \ +) + +/* Octet 28 */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) +#define BLE_SUPP_CMD_LE_START_ENCRYPT (1 << 0) +#define BLE_SUPP_CMD_LE_LTK_REQ_REPLY (1 << 1) +#define BLE_SUPP_CMD_LE_LTK_REQ_NEG_REPLY (1 << 2) +#else +#define BLE_SUPP_CMD_LE_START_ENCRYPT (0 << 0) +#define BLE_SUPP_CMD_LE_LTK_REQ_REPLY (0 << 1) +#define BLE_SUPP_CMD_LE_LTK_REQ_NEG_REPLY (0 << 2) +#endif +#define BLE_SUPP_CMD_LE_READ_SUPP_STATES (1 << 3) + +#if MYNEWT_VAL(BLE_LL_DTM) +#define BLE_SUPP_CMD_LE_RX_TEST (1 << 4) +#define BLE_SUPP_CMD_LE_TX_TEST (1 << 5) +#define BLE_SUPP_CMD_LE_TEST_END (1 << 6) + +#else +#define BLE_SUPP_CMD_LE_RX_TEST (0 << 4) +#define BLE_SUPP_CMD_LE_TX_TEST (0 << 5) +#define BLE_SUPP_CMD_LE_TEST_END (0 << 6) +#endif + +#define BLE_LL_SUPP_CMD_OCTET_28 \ +( \ + BLE_SUPP_CMD_LE_START_ENCRYPT | \ + BLE_SUPP_CMD_LE_LTK_REQ_REPLY | \ + BLE_SUPP_CMD_LE_LTK_REQ_NEG_REPLY | \ + BLE_SUPP_CMD_LE_READ_SUPP_STATES | \ + BLE_SUPP_CMD_LE_RX_TEST | \ + BLE_SUPP_CMD_LE_TX_TEST | \ + BLE_SUPP_CMD_LE_TEST_END \ +) + +/* Octet 33 */ +#define BLE_SUPP_CMD_LE_REM_CONN_PRR (1 << 4) +#define BLE_SUPP_CMD_LE_REM_CONN_PRNR (1 << 5) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) +#define BLE_SUPP_CMD_LE_SET_DATALEN (1 << 6) +#define BLE_SUPP_CMD_LE_RD_SUGG_DATALEN (1 << 7) +#else +#define BLE_SUPP_CMD_LE_SET_DATALEN (0 << 6) +#define BLE_SUPP_CMD_LE_RD_SUGG_DATALEN (0 << 7) +#endif + +#define BLE_LL_SUPP_CMD_OCTET_33 \ +( \ + BLE_SUPP_CMD_LE_REM_CONN_PRR | \ + BLE_SUPP_CMD_LE_REM_CONN_PRNR | \ + BLE_SUPP_CMD_LE_SET_DATALEN | \ + BLE_SUPP_CMD_LE_RD_SUGG_DATALEN \ +) + +/* Octet 34 */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) +#define BLE_SUPP_CMD_LE_WR_SUGG_DATALEN (1 << 0) +#else +#define BLE_SUPP_CMD_LE_WR_SUGG_DATALEN (0 << 0) +#endif +#define BLE_SUPP_CMD_LE_READ_LOCAL_P256_PK (0 << 1) +#define BLE_SUPP_CMD_LE_GENERATE_DH_KEY (0 << 2) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) +#define BLE_SUPP_CMD_LE_ADD_RESOLV_LIST (1 << 3) +#define BLE_SUPP_CMD_LE_REMOVE_RESOLV_LIST (1 << 4) +#define BLE_SUPP_CMD_LE_CLEAR_RESOLV_LIST (1 << 5) +#define BLE_SUPP_CMD_LE_RD_RESOLV_SIZE (1 << 6) +#define BLE_SUPP_CMD_LE_RD_PEER_RESV_ADDR (1 << 7) +#else +#define BLE_SUPP_CMD_LE_ADD_RESOLV_LIST (0 << 3) +#define BLE_SUPP_CMD_LE_REMOVE_RESOLV_LIST (0 << 4) +#define BLE_SUPP_CMD_LE_CLEAR_RESOLV_LIST (0 << 5) +#define BLE_SUPP_CMD_LE_RD_RESOLV_SIZE (0 << 6) +#define BLE_SUPP_CMD_LE_RD_PEER_RESV_ADDR (0 << 7) +#endif + +#define BLE_LL_SUPP_CMD_OCTET_34 \ +( \ + BLE_SUPP_CMD_LE_WR_SUGG_DATALEN | \ + BLE_SUPP_CMD_LE_READ_LOCAL_P256_PK | \ + BLE_SUPP_CMD_LE_GENERATE_DH_KEY | \ + BLE_SUPP_CMD_LE_ADD_RESOLV_LIST | \ + BLE_SUPP_CMD_LE_REMOVE_RESOLV_LIST | \ + BLE_SUPP_CMD_LE_CLEAR_RESOLV_LIST | \ + BLE_SUPP_CMD_LE_RD_RESOLV_SIZE | \ + BLE_SUPP_CMD_LE_RD_PEER_RESV_ADDR \ +) + +/* Octet 35 */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) +#define BLE_SUPP_CMD_LE_RD_LOCAL_RESV_ADDR (1 << 0) +#define BLE_SUPP_CMD_LE_SET_ADDR_RES_EN (1 << 1) +#define BLE_SUPP_CMD_LE_SET_RESV_ADDR_TMO (1 << 2) +#else +#define BLE_SUPP_CMD_LE_RD_LOCAL_RESV_ADDR (0 << 0) +#define BLE_SUPP_CMD_LE_SET_ADDR_RES_EN (0 << 1) +#define BLE_SUPP_CMD_LE_SET_RESV_ADDR_TMO (0 << 2) +#endif +#define BLE_SUPP_CMD_LE_RD_MAX_DATALEN (1 << 3) +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#define BLE_SUPP_CMD_LE_READ_PHY (1 << 4) +#define BLE_SUPP_CMD_LE_SET_DEFAULT_PHY (1 << 5) +#define BLE_SUPP_CMD_LE_SET_PHY (1 << 6) +#else +#define BLE_SUPP_CMD_LE_READ_PHY (0 << 4) +#define BLE_SUPP_CMD_LE_SET_DEFAULT_PHY (0 << 5) +#define BLE_SUPP_CMD_LE_SET_PHY (0 << 6) +#endif + +#if MYNEWT_VAL(BLE_LL_DTM) +#define BLE_SUPP_CMD_LE_ENHANCED_RX_TEST (1 << 7) +#else +#define BLE_SUPP_CMD_LE_ENHANCED_RX_TEST (0 << 7) +#endif + +#define BLE_LL_SUPP_CMD_OCTET_35 \ +( \ + BLE_SUPP_CMD_LE_RD_LOCAL_RESV_ADDR | \ + BLE_SUPP_CMD_LE_SET_ADDR_RES_EN | \ + BLE_SUPP_CMD_LE_SET_RESV_ADDR_TMO | \ + BLE_SUPP_CMD_LE_RD_MAX_DATALEN | \ + BLE_SUPP_CMD_LE_READ_PHY | \ + BLE_SUPP_CMD_LE_SET_DEFAULT_PHY | \ + BLE_SUPP_CMD_LE_SET_PHY | \ + BLE_SUPP_CMD_LE_ENHANCED_RX_TEST \ +) + +/* Octet 36 */ +#if MYNEWT_VAL(BLE_LL_DTM) +#define BLE_SUPP_CMD_LE_ENHANCED_TX_TEST (1 << 0) +#else +#define BLE_SUPP_CMD_LE_ENHANCED_TX_TEST (0 << 0) +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +#define BLE_SUPP_CMD_LE_SET_ADVS_RAND_ADDR (1 << 1) +#define BLE_SUPP_CMD_LE_SET_EXT_ADV_PARAM (1 << 2) +#define BLE_SUPP_CMD_LE_SET_EXT_ADV_DATA (1 << 3) +#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_RSP (1 << 4) +#define BLE_SUPP_CMD_LE_SET_EXT_ADV_ENABLE (1 << 5) +#define BLE_SUPP_CMD_LE_RD_MAX_ADV_DATA_LEN (1 << 6) +#define BLE_SUPP_CMD_LE_RD_NUM_SUPP_ADVS (1 << 7) +#else +#define BLE_SUPP_CMD_LE_SET_ADVS_RAND_ADDR (0 << 1) +#define BLE_SUPP_CMD_LE_SET_EXT_ADV_PARAM (0 << 2) +#define BLE_SUPP_CMD_LE_SET_EXT_ADV_DATA (0 << 3) +#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_RSP (0 << 4) +#define BLE_SUPP_CMD_LE_SET_EXT_ADV_ENABLE (0 << 5) +#define BLE_SUPP_CMD_LE_RD_MAX_ADV_DATA_LEN (0 << 6) +#define BLE_SUPP_CMD_LE_RD_NUM_SUPP_ADVS (0 << 7) +#endif + +#define BLE_LL_SUPP_CMD_OCTET_36 \ +( \ + BLE_SUPP_CMD_LE_ENHANCED_TX_TEST | \ + BLE_SUPP_CMD_LE_SET_ADVS_RAND_ADDR | \ + BLE_SUPP_CMD_LE_SET_EXT_ADV_PARAM | \ + BLE_SUPP_CMD_LE_SET_EXT_ADV_DATA | \ + BLE_SUPP_CMD_LE_SET_EXT_SCAN_RSP | \ + BLE_SUPP_CMD_LE_SET_EXT_ADV_ENABLE | \ + BLE_SUPP_CMD_LE_RD_MAX_ADV_DATA_LEN | \ + BLE_SUPP_CMD_LE_RD_NUM_SUPP_ADVS \ +) + +/* Octet 37 */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +#define BLE_SUPP_CMD_LE_REMOVE_ADVS (1 << 0) +#define BLE_SUPP_CMD_LE_CLEAR_ADVS (1 << 1) +#else +#define BLE_SUPP_CMD_LE_REMOVE_ADVS (0 << 0) +#define BLE_SUPP_CMD_LE_CLEAR_ADVS (0 << 1) +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) +#define BLE_SUPP_CMD_LE_SET_PADV_PARAM (1 << 2) +#define BLE_SUPP_CMD_LE_SET_PADV_DATA (1 << 3) +#define BLE_SUPP_CMD_LE_SET_PADV_ENABLE (1 << 4) +#else +#define BLE_SUPP_CMD_LE_SET_PADV_PARAM (0 << 2) +#define BLE_SUPP_CMD_LE_SET_PADV_DATA (0 << 3) +#define BLE_SUPP_CMD_LE_SET_PADV_ENABLE (0 << 4) +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_PARAM (1 << 5) +#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_ENABLE (1 << 6) +#define BLE_SUPP_CMD_LE_EXT_CREATE_CONN (1 << 7) +#else +#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_PARAM (0 << 5) +#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_ENABLE (0 << 6) +#define BLE_SUPP_CMD_LE_EXT_CREATE_CONN (0 << 7) +#endif + +#define BLE_LL_SUPP_CMD_OCTET_37 \ +( \ + BLE_SUPP_CMD_LE_REMOVE_ADVS | \ + BLE_SUPP_CMD_LE_CLEAR_ADVS | \ + BLE_SUPP_CMD_LE_SET_PADV_PARAM | \ + BLE_SUPP_CMD_LE_SET_PADV_DATA | \ + BLE_SUPP_CMD_LE_SET_PADV_ENABLE | \ + BLE_SUPP_CMD_LE_SET_EXT_SCAN_PARAM | \ + BLE_SUPP_CMD_LE_SET_EXT_SCAN_ENABLE | \ + BLE_SUPP_CMD_LE_EXT_CREATE_CONN \ +) + +/* Octet 38 */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) +#define BLE_SUPP_CMD_LE_PADV_CREATE_SYNC (1 << 0) +#define BLE_SUPP_CMD_LE_PADV_CREATE_SYNC_C (1 << 1) +#define BLE_SUPP_CMD_LE_PADV_TERMINATE_SYNC (1 << 2) +#define BLE_SUPP_CMD_LE_ADD_PADV_LIST (1 << 3) +#define BLE_SUPP_CMD_LE_REMOVE_PADV_LIST (1 << 4) +#define BLE_SUPP_CMD_LE_CLEAR_PADV_LIST (1 << 5) +#define BLE_SUPP_CMD_LE_RD_PADV_LIST_SIZE (1 << 6) +#else +#define BLE_SUPP_CMD_LE_PADV_CREATE_SYNC (0 << 0) +#define BLE_SUPP_CMD_LE_PADV_CREATE_SYNC_C (0 << 1) +#define BLE_SUPP_CMD_LE_PADV_TERMINATE_SYNC (0 << 2) +#define BLE_SUPP_CMD_LE_ADD_PADV_LIST (0 << 3) +#define BLE_SUPP_CMD_LE_REMOVE_PADV_LIST (0 << 4) +#define BLE_SUPP_CMD_LE_CLEAR_PADV_LIST (0 << 5) +#define BLE_SUPP_CMD_LE_RD_PADV_LIST_SIZE (0 << 6) +#endif +#define BLE_SUPP_CMD_LE_RD_TX_POWER (1 << 7) + +#define BLE_LL_SUPP_CMD_OCTET_38 \ +( \ + BLE_SUPP_CMD_LE_PADV_CREATE_SYNC | \ + BLE_SUPP_CMD_LE_PADV_CREATE_SYNC_C | \ + BLE_SUPP_CMD_LE_PADV_TERMINATE_SYNC | \ + BLE_SUPP_CMD_LE_ADD_PADV_LIST | \ + BLE_SUPP_CMD_LE_REMOVE_PADV_LIST | \ + BLE_SUPP_CMD_LE_CLEAR_PADV_LIST | \ + BLE_SUPP_CMD_LE_RD_PADV_LIST_SIZE | \ + BLE_SUPP_CMD_LE_RD_TX_POWER \ +) + +/* Octet 39 */ +#define BLE_SUPP_CMD_LE_RD_RF_PATH_COMP (1 << 0) +#define BLE_SUPP_CMD_LE_WR_RF_PATH_COMP (1 << 1) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) +#define BLE_SUPP_CMD_LE_SET_PRIVACY_MODE (1 << 2) +#else +#define BLE_SUPP_CMD_LE_SET_PRIVACY_MODE (0 << 2) +#endif + +#define BLE_LL_SUPP_CMD_OCTET_39 \ +( \ + BLE_SUPP_CMD_LE_RD_RF_PATH_COMP | \ + BLE_SUPP_CMD_LE_WR_RF_PATH_COMP | \ + BLE_SUPP_CMD_LE_SET_PRIVACY_MODE \ +) + +/* Octet 40 */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) && MYNEWT_VAL(BLE_VERSION) >= 51 +#define BLE_SUPP_CMD_LE_PADV_RECV_ENABLE (1 << 5) +#else +#define BLE_SUPP_CMD_LE_PADV_RECV_ENABLE (0 << 5) +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) +#define BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER (1 << 6) +#define BLE_SUPP_CMD_LE_PADV_SET_INFO_TRANSFER (1 << 7) +#else +#define BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER (0 << 6) +#define BLE_SUPP_CMD_LE_PADV_SET_INFO_TRANSFER (0 << 7) +#endif + +#define BLE_LL_SUPP_CMD_OCTET_40 \ +( \ + BLE_SUPP_CMD_LE_PADV_RECV_ENABLE | \ + BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER | \ + BLE_SUPP_CMD_LE_PADV_SET_INFO_TRANSFER \ +) + +/* Octet 41 */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) +#define BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS (1 << 0) +#define BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS (1 << 1) +#else +#define BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS (0 << 0) +#define BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS (0 << 1) +#endif +#define BLE_LL_SUPP_CMD_OCTET_41 \ +( \ + BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS | \ + BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS \ +) + +/* Defines the array of supported commands */ +const uint8_t g_ble_ll_supp_cmds[BLE_LL_SUPP_CMD_LEN] = +{ + BLE_LL_SUPP_CMD_OCTET_0, /* Octet 0 */ + 0, + 0, + 0, + 0, + BLE_LL_SUPP_CMD_OCTET_5, + 0, + 0, + 0, /* Octet 8 */ + 0, + BLE_LL_SUPP_CMD_OCTET_10, + 0, + 0, + 0, + BLE_LL_SUPP_CMD_OCTET_14, + BLE_LL_SUPP_CMD_OCTET_15, + 0, /* Octet 16 */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, /* Octet 24 */ + BLE_LL_SUPP_CMD_OCTET_25, + BLE_LL_SUPP_CMD_OCTET_26, + BLE_LL_SUPP_CMD_OCTET_27, + BLE_LL_SUPP_CMD_OCTET_28, + 0, + 0, + 0, + 0, /* Octet 32 */ + BLE_LL_SUPP_CMD_OCTET_33, + BLE_LL_SUPP_CMD_OCTET_34, + BLE_LL_SUPP_CMD_OCTET_35, + BLE_LL_SUPP_CMD_OCTET_36, + BLE_LL_SUPP_CMD_OCTET_37, + BLE_LL_SUPP_CMD_OCTET_38, + BLE_LL_SUPP_CMD_OCTET_39, + BLE_LL_SUPP_CMD_OCTET_40, /* Octet 40 */ + BLE_LL_SUPP_CMD_OCTET_41, +}; + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_sync.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_sync.c new file mode 100644 index 000000000..231a4d633 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_sync.c @@ -0,0 +1,2248 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef ESP_PLATFORM + +#include +#include +#include + +#include "nimble/porting/nimble/include/syscfg/syscfg.h" + +#include "../include/controller/ble_ll.h" +#include "../include/controller/ble_ll_hci.h" +#include "../include/controller/ble_ll_sync.h" +#include "../include/controller/ble_ll_utils.h" +#include "../include/controller/ble_ll_sched.h" +#include "../include/controller/ble_ll_whitelist.h" +#include "../include/controller/ble_ll_scan.h" +#include "../include/controller/ble_ll_resolv.h" +#include "../include/controller/ble_ll_rfmgmt.h" + +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/include/nimble/hci_common.h" +#include "nimble/nimble/include/nimble/ble_hci_trans.h" + +#include "ble_ll_conn_priv.h" + +#include "nimble/porting/nimble/include/stats/stats.h" + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + +/* defines number of events that can be lost during sync establishment + * before failed to be established error is reported + */ +#define BLE_LL_SYNC_ESTABLISH_CNT 6 + +#define BLE_LL_SYNC_CNT MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_CNT) +#define BLE_LL_SYNC_LIST_CNT MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_LIST_CNT) + +#define BLE_LL_SYNC_SM_FLAG_RESERVED 0x0001 +#define BLE_LL_SYNC_SM_FLAG_ESTABLISHING 0x0002 +#define BLE_LL_SYNC_SM_FLAG_ESTABLISHED 0x0004 +#define BLE_LL_SYNC_SM_FLAG_SET_ANCHOR 0x0008 +#define BLE_LL_SYNC_SM_FLAG_OFFSET_300 0x0010 +#define BLE_LL_SYNC_SM_FLAG_SYNC_INFO 0x0020 +#define BLE_LL_SYNC_SM_FLAG_DISABLED 0x0040 +#define BLE_LL_SYNC_SM_FLAG_ADDR_RESOLVED 0x0080 +#define BLE_LL_SYNC_SM_FLAG_HCI_TRUNCATED 0x0100 + +#define BLE_LL_SYNC_CHMAP_LEN 5 +#define BLE_LL_SYNC_ITVL_USECS 1250 + +struct ble_ll_sync_sm { + uint16_t flags; + + uint8_t adv_sid; + uint8_t adv_addr[BLE_DEV_ADDR_LEN]; + uint8_t adv_addr_type; + + uint8_t sca; + uint8_t chanmap[BLE_LL_SYNC_CHMAP_LEN]; + uint8_t num_used_chans; + + uint8_t chan_index; + uint8_t chan_chain; + + uint8_t phy_mode; + + uint8_t sync_pending_cnt; + + uint32_t timeout; + uint16_t skip; + + uint16_t itvl; + uint8_t itvl_usecs; + uint32_t itvl_ticks; + + uint32_t crcinit; /* only 3 bytes are used */ + uint32_t access_addr; + uint16_t event_cntr; + uint16_t channel_id; + + uint32_t window_widening; + uint32_t last_anchor_point; + uint32_t anchor_point; + uint8_t anchor_point_usecs; + + struct ble_ll_sched_item sch; + + struct ble_npl_event sync_ev_end; + + uint8_t *next_report; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) + struct ble_ll_conn_sm *transfer_conn; + uint8_t *transfer_received_ev; + uint16_t transfer_id; + uint16_t event_cntr_last_received; + uint8_t adv_addr_rpa[6]; +#endif +}; + +static struct ble_ll_sync_sm g_ble_ll_sync_sm[BLE_LL_SYNC_CNT]; + +static struct { + uint8_t adv_sid; + uint8_t adv_addr[BLE_DEV_ADDR_LEN]; + uint8_t adv_addr_type; +} g_ble_ll_sync_adv_list[BLE_LL_SYNC_LIST_CNT]; + +static struct { + uint32_t timeout; + uint16_t max_skip; + uint16_t options; +} g_ble_ll_sync_create_params; + +/* if this is set HCI LE Sync Create is pending */ +static uint8_t *g_ble_ll_sync_create_comp_ev; + +static struct ble_ll_sync_sm *g_ble_ll_sync_sm_current; + +static int +ble_ll_sync_on_list(const uint8_t *addr, uint8_t addr_type, uint8_t sid) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(g_ble_ll_sync_adv_list); i++) { + if ((g_ble_ll_sync_adv_list[i].adv_sid == sid) && + (g_ble_ll_sync_adv_list[i].adv_addr_type == addr_type) && + !memcmp(g_ble_ll_sync_adv_list[i].adv_addr, addr, BLE_DEV_ADDR_LEN)) { + return i; + } + } + + return -1; +} + +static int +ble_ll_sync_list_get_free(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(g_ble_ll_sync_adv_list); i++) { + if (g_ble_ll_sync_adv_list[i].adv_sid == 0xff) { + return i; + } + } + + return -1; +} + +static bool +ble_ll_sync_list_empty(void) { + int i; + + for (i = 0; i < ARRAY_SIZE(g_ble_ll_sync_adv_list); i++) { + if (g_ble_ll_sync_adv_list[i].adv_sid != 0xff) { + return false; + } + } + + return true; +} + +static uint8_t +ble_ll_sync_get_handle(struct ble_ll_sync_sm *sm) +{ + /* handle number is offset in global array */ + return sm - g_ble_ll_sync_sm; +} + +static void +ble_ll_sync_sm_clear(struct ble_ll_sync_sm *sm) +{ + if (sm->flags & (BLE_LL_SYNC_SM_FLAG_ESTABLISHING | + BLE_LL_SYNC_SM_FLAG_ESTABLISHED)) { + ble_ll_sched_rmv_elem(&sm->sch); + ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &sm->sync_ev_end); + } + + if (sm->next_report) { + ble_hci_trans_buf_free(sm->next_report); + } + + if (g_ble_ll_sync_sm_current == sm) { + ble_phy_disable(); + ble_ll_state_set(BLE_LL_STATE_STANDBY); + g_ble_ll_sync_sm_current = NULL; + ble_ll_scan_chk_resume(); + } + + ble_ll_rfmgmt_release(); + + BLE_LL_ASSERT(sm->sync_ev_end.ev.ev_queued == 0); + BLE_LL_ASSERT(sm->sch.enqueued == 0); + memset(sm, 0, sizeof(*sm)); +} + +static uint8_t +ble_ll_sync_phy_mode_to_hci(int8_t phy_mode) +{ +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + switch (phy_mode) { + case BLE_PHY_MODE_1M: + return BLE_HCI_LE_PHY_1M; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) + case BLE_PHY_MODE_2M: + return BLE_HCI_LE_PHY_2M; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + case BLE_PHY_MODE_CODED_125KBPS: + case BLE_PHY_MODE_CODED_500KBPS: + return BLE_HCI_LE_PHY_CODED; +#endif + default: + BLE_LL_ASSERT(false); + return BLE_PHY_MODE_1M; + } +#else + return BLE_PHY_MODE_1M; +#endif +} + +static struct ble_ll_sync_sm * +ble_ll_sync_find(const uint8_t *addr, uint8_t addr_type, uint8_t sid) +{ + struct ble_ll_sync_sm *sm; + int i; + + for (i = 0; i < BLE_LL_SYNC_CNT; i++) { + sm = &g_ble_ll_sync_sm[i]; + + if (!sm->flags) { + continue; + } + if ((sm->adv_sid == sid) && (sm->adv_addr_type == addr_type) && + !memcmp(&sm->adv_addr, addr, BLE_DEV_ADDR_LEN)) { + return sm; + } + } + + return NULL; +} + +static uint16_t +get_max_skip(uint32_t interval_us, uint32_t timeout_us) +{ + uint16_t max_skip; + + BLE_LL_ASSERT(interval_us); + BLE_LL_ASSERT(timeout_us); + + if (timeout_us <= interval_us) { + return 0; + } + + /* + * Calculate max allowed skip to receive something before timeout. We adjust + * current skip value to be no more than max_skip-6 so we have at least few + * attempts to receive an event (so we don't timeout immediately after just + * one missed event). + */ + + max_skip = (timeout_us / interval_us) - 1; + + if (max_skip < 6) { + return 0; + } + + return max_skip - 6; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) +static void +ble_ll_sync_transfer_received(struct ble_ll_sync_sm *sm, uint8_t status) +{ + struct ble_hci_ev_le_subev_periodic_adv_sync_transfer *ev; + struct ble_hci_ev *hci_ev; + + BLE_LL_ASSERT(sm->transfer_received_ev); + + if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_TRANSFER)) { + hci_ev = (void *) sm->transfer_received_ev; + + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*ev); + + ev = (void *) hci_ev->data; + ev->subev_code = BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_TRANSFER; + + ev->status = status; + ev->conn_handle = htole16(sm->transfer_conn->conn_handle); + ev->service_data = htole16(sm->transfer_id); + + /* this is ignored by host on error */ + ev->sync_handle = htole16(ble_ll_sync_get_handle(sm)); + ev->sid = sm->adv_sid; + ev->peer_addr_type = sm->adv_addr_type; + if (sm->flags & BLE_LL_SYNC_SM_FLAG_ADDR_RESOLVED) { + ev->peer_addr_type += 2; + } + memcpy(ev->peer_addr, sm->adv_addr, BLE_DEV_ADDR_LEN); + ev->phy = ble_ll_sync_phy_mode_to_hci(sm->phy_mode); + ev->interval = htole16(sm->itvl); + ev->aca = sm->sca; + + ble_ll_hci_event_send(hci_ev); + } else { + ble_hci_trans_buf_free(sm->transfer_received_ev); + } + + sm->transfer_received_ev = NULL; + sm->transfer_conn = NULL; +} +#endif + +static void +ble_ll_sync_est_event_success(struct ble_ll_sync_sm *sm) +{ + struct ble_hci_ev_le_subev_periodic_adv_sync_estab *ev; + struct ble_hci_ev *hci_ev; + + BLE_LL_ASSERT(g_ble_ll_sync_create_comp_ev); + + if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB)) { + hci_ev = (void *) g_ble_ll_sync_create_comp_ev; + + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*ev); + ev = (void *) hci_ev->data; + + ev->subev_code = BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB; + ev->status = BLE_ERR_SUCCESS; + ev->sync_handle = htole16(ble_ll_sync_get_handle(sm)); + ev->sid = sm->adv_sid; + ev->peer_addr_type = sm->adv_addr_type; + if (sm->flags & BLE_LL_SYNC_SM_FLAG_ADDR_RESOLVED) { + ev->peer_addr_type += 2; + } + memcpy(ev->peer_addr, sm->adv_addr, BLE_DEV_ADDR_LEN); + ev->phy = ble_ll_sync_phy_mode_to_hci(sm->phy_mode); + ev->interval = htole16(sm->itvl); + ev->aca = sm->sca; + + ble_ll_hci_event_send(hci_ev); + } else { + ble_hci_trans_buf_free(g_ble_ll_sync_create_comp_ev); + } + + g_ble_ll_sync_create_comp_ev = NULL; +} + +static void +ble_ll_sync_est_event_failed(uint8_t status) +{ + struct ble_hci_ev_le_subev_periodic_adv_sync_estab *ev; + struct ble_hci_ev *hci_ev; + + BLE_LL_ASSERT(g_ble_ll_sync_create_comp_ev); + + if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB)) { + hci_ev = (void *) g_ble_ll_sync_create_comp_ev; + + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*ev); + ev = (void *) hci_ev->data; + + memset(ev, 0, sizeof(*ev)); + + ev->subev_code = BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB; + ev->status = status; + + ble_ll_hci_event_send(hci_ev); + } else { + ble_hci_trans_buf_free(g_ble_ll_sync_create_comp_ev); + } + + g_ble_ll_sync_create_comp_ev = NULL; +} + +static void +ble_ll_sync_lost_event(struct ble_ll_sync_sm *sm) +{ + struct ble_hci_ev_le_subev_periodic_adv_sync_lost *ev; + struct ble_hci_ev *hci_ev; + + if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_LOST)) { + hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (hci_ev) { + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*ev); + ev = (void *) hci_ev->data; + + ev->subev_code = BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_LOST; + ev->sync_handle = htole16(ble_ll_sync_get_handle(sm)); + + ble_ll_hci_event_send(hci_ev); + } + } +} + +static void +ble_ll_sync_current_sm_over(void) +{ + /* Disable the PHY */ + ble_phy_disable(); + + /* Link-layer is in standby state now */ + ble_ll_state_set(BLE_LL_STATE_STANDBY); + + /* Set current LL sync to NULL */ + g_ble_ll_sync_sm_current = NULL; +} + +static int +ble_ll_sync_event_start_cb(struct ble_ll_sched_item *sch) +{ + struct ble_ll_sync_sm *sm; + uint32_t wfr_usecs; + uint32_t start; + int rc; + + /* Set current connection state machine */ + sm = sch->cb_arg; + BLE_LL_ASSERT(sm); + + g_ble_ll_sync_sm_current = sm; + + /* Disable whitelisting */ + ble_ll_whitelist_disable(); + + /* Set LL state */ + ble_ll_state_set(BLE_LL_STATE_SYNC); + + /* Set channel */ + ble_phy_setchan(sm->chan_index, sm->access_addr, sm->crcinit); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + ble_phy_resolv_list_disable(); +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + ble_phy_encrypt_disable(); +#endif + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + ble_phy_mode_set(sm->phy_mode, sm->phy_mode); +#endif + + start = sch->start_time + g_ble_ll_sched_offset_ticks; + rc = ble_phy_rx_set_start_time(start, sch->remainder); + if (rc && rc != BLE_PHY_ERR_RX_LATE) { + STATS_INC(ble_ll_stats, sync_event_failed); + rc = BLE_LL_SCHED_STATE_DONE; + ble_ll_event_send(&sm->sync_ev_end); + ble_ll_sync_current_sm_over(); + } else { + /* + * Set flag that tells to set last anchor point if a packet + * has been received. + */ + sm->flags |= BLE_LL_SYNC_SM_FLAG_SET_ANCHOR; + + /* Set WFR timer. + * If establishing we always adjust with offset unit. + * If this is first packet of sync (one that was pointed by from + * SyncInfo we don't adjust WFT with window widening. + */ + if (sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING) { + wfr_usecs = (sm->flags & BLE_LL_SYNC_SM_FLAG_OFFSET_300) ? 300 : 30; + if (!(sm->flags & BLE_LL_SYNC_SM_FLAG_SYNC_INFO)) { + wfr_usecs += 2 * sm->window_widening; + } + } else { + wfr_usecs = 2 * sm->window_widening; + } + ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_RX, 0, wfr_usecs); + + rc = BLE_LL_SCHED_STATE_RUNNING; + } + + sm->flags &= ~BLE_LL_SYNC_SM_FLAG_SYNC_INFO; + + return rc; +} + +/** + * Called when a receive PDU has started. + * + * Context: interrupt + * + * @return int + * < 0: A frame we dont want to receive. + * = 0: Continue to receive frame. Dont go from rx to tx + */ +int +ble_ll_sync_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *rxhdr) +{ + BLE_LL_ASSERT(g_ble_ll_sync_sm_current); + + /* this also handles chains as those have same PDU type */ + if (pdu_type != BLE_ADV_PDU_TYPE_AUX_SYNC_IND) { + ble_ll_event_send(&g_ble_ll_sync_sm_current->sync_ev_end); + ble_ll_sync_current_sm_over(); + STATS_INC(ble_ll_stats, sched_invalid_pdu); + return -1; + } + + STATS_INC(ble_ll_stats, sync_received); + return 0; +} + +static int +ble_ll_sync_parse_ext_hdr(struct os_mbuf *om, uint8_t **aux, int8_t *tx_power) +{ + uint8_t *rxbuf = om->om_data; + uint8_t ext_hdr_flags; + uint8_t ext_hdr_len; + uint8_t *ext_hdr; + uint8_t pdu_len; + int i; + + pdu_len = rxbuf[1]; + if (pdu_len == 0) { + return -1; + } + ext_hdr_len = rxbuf[2] & 0x3F; + if (ext_hdr_len > (pdu_len - 1)) { + return -1; + } + + if (ext_hdr_len) { + ext_hdr_flags = rxbuf[3]; + ext_hdr = &rxbuf[4]; + + i = 0; + + /* there should be no AdvA in Sync or chain, skip it */ + if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) { + i += BLE_LL_EXT_ADV_ADVA_SIZE; + } + + /* there should be no TargetA in Sync or chain, skip it */ + if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) { + i += BLE_LL_EXT_ADV_TARGETA_SIZE; + } + + /* Ignore CTE for now */ + if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_CTE_INFO_BIT)) { + i += 1; + } + + /* there should be no ADI in Sync or chain, skip it */ + if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) { + i += BLE_LL_EXT_ADV_DATA_INFO_SIZE; + } + + /* get AuXPTR if present */ + if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) { + *aux = ext_hdr + i; + i += BLE_LL_EXT_ADV_AUX_PTR_SIZE; + } + + /* there should be no SyncInfo in Sync or chain, skip it */ + if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_SYNC_INFO_BIT)) { + i += BLE_LL_EXT_ADV_SYNC_INFO_SIZE; + } + + if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_TX_POWER_BIT)) { + *tx_power = *(ext_hdr + i); + i += BLE_LL_EXT_ADV_TX_POWER_SIZE; + } + + /* TODO Handle ACAD if needed */ + + /* sanity check */ + if (i > ext_hdr_len) { + return -1; + } + } + + return pdu_len - ext_hdr_len - 1; +} + +static void +ble_ll_sync_adjust_ext_hdr(struct os_mbuf *om) +{ + uint8_t *rxbuf = om->om_data; + uint8_t ext_hdr_len; + + /* this was already verified in ble_ll_sync_parse_ext_hdr() */ + ext_hdr_len = rxbuf[2] & 0x3F; + + os_mbuf_adj(om, 3 + ext_hdr_len); +} + +static void +ble_ll_sync_send_truncated_per_adv_rpt(struct ble_ll_sync_sm *sm, uint8_t *evbuf) +{ + struct ble_hci_ev_le_subev_periodic_adv_rpt *ev; + struct ble_hci_ev *hci_ev; + + if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT) || + (sm->flags & BLE_LL_SYNC_SM_FLAG_DISABLED)) { + ble_hci_trans_buf_free(evbuf); + return; + } + + hci_ev = (void *) evbuf; + + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*ev); + ev = (void *) hci_ev->data; + + ev->subev_code = BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT; + ev->sync_handle = htole16(ble_ll_sync_get_handle(sm)); + ev->tx_power = 127; /* not available */ + ev->rssi = 127; /* not available */ + ev->cte_type = 0xff; + ev->data_status = BLE_HCI_PERIODIC_DATA_STATUS_TRUNCATED; + ev->data_len = 0; + + ble_ll_hci_event_send(hci_ev); +} + +static void +ble_ll_sync_send_per_adv_rpt(struct ble_ll_sync_sm *sm, struct os_mbuf *rxpdu, + int8_t rssi, int8_t tx_power, int datalen, + uint8_t *aux, bool aux_scheduled) +{ + struct ble_hci_ev_le_subev_periodic_adv_rpt *ev; + struct ble_hci_ev *hci_ev; + struct ble_hci_ev *hci_ev_next = NULL; + uint8_t max_data_len; + int offset; + + /* use next report buffer if present, this means we are chaining */ + if (sm->next_report) { + hci_ev = (void *) sm->next_report; + sm->next_report = NULL; + } else { + hci_ev = (void * )ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO); + if (!hci_ev) { + goto done; + } + } + + max_data_len = BLE_LL_MAX_EVT_LEN - sizeof(*hci_ev) - sizeof(*ev); + offset = 0; + + do { + if (hci_ev_next) { + hci_ev = hci_ev_next; + hci_ev_next = NULL; + } + + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*ev); + + ev = (void *) hci_ev->data; + + ev->subev_code = BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT; + ev->sync_handle = htole16(ble_ll_sync_get_handle(sm)); + ev->tx_power = tx_power; + ev->rssi = rssi; + ev->cte_type = 0xff; + + ev->data_len = min(max_data_len, datalen - offset); + /* adjust event length */ + hci_ev->length += ev->data_len; + + os_mbuf_copydata(rxpdu, offset, ev->data_len, ev->data); + offset += ev->data_len; + + /* Need another event for next fragment of this PDU */ + if (offset < datalen) { + hci_ev_next = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO); + if (hci_ev_next) { + ev->data_status = BLE_HCI_PERIODIC_DATA_STATUS_INCOMPLETE; + } else { + ev->data_status = BLE_HCI_PERIODIC_DATA_STATUS_TRUNCATED; + } + } else { + /* last report of this PDU */ + if (aux) { + if (aux_scheduled) { + /* if we scheduled aux, we need buffer for next report */ + hci_ev_next = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO); + if (hci_ev_next) { + ev->data_status = BLE_HCI_PERIODIC_DATA_STATUS_INCOMPLETE; + } else { + ev->data_status = BLE_HCI_PERIODIC_DATA_STATUS_TRUNCATED; + } + } else { + ev->data_status = BLE_HCI_PERIODIC_DATA_STATUS_TRUNCATED; + } + } else { + ev->data_status = BLE_HCI_PERIODIC_DATA_STATUS_COMPLETE; + } + } + ble_ll_hci_event_send(hci_ev); + } while ((offset < datalen) && hci_ev_next); + +done: + /* this means that we already truncated data (or didn't sent first at all) + * in HCI report but has scheduled for next PDU in chain. In that case mark + * it so that we end event properly when next PDU is received. + * */ + if (aux_scheduled && !hci_ev_next) { + sm->flags |= BLE_LL_SYNC_SM_FLAG_HCI_TRUNCATED; + } + + /* store for chain */ + sm->next_report = (void *) hci_ev_next; +} + +/** + * Called when a receive PDU has ended. + * + * Context: Interrupt + * + * @param rxpdu + * + * @return int + * < 0: Disable the phy after reception. + * == 0: Success. Do not disable the PHY. + * > 0: Do not disable PHY as that has already been done. + */ +int +ble_ll_sync_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) +{ + struct ble_mbuf_hdr *ble_hdr; + struct os_mbuf *rxpdu; + + BLE_LL_ASSERT(g_ble_ll_sync_sm_current); + + /* type was verified in isr_start */ + + rxpdu = ble_ll_rxpdu_alloc(rxbuf[1] + BLE_LL_PDU_HDR_LEN); + if (rxpdu) { + ble_phy_rxpdu_copy(rxbuf, rxpdu); + + ble_hdr = BLE_MBUF_HDR_PTR(rxpdu); + ble_hdr->rxinfo.user_data = g_ble_ll_sync_sm_current; + + ble_ll_rx_pdu_in(rxpdu); + } else { + STATS_INC(ble_ll_stats, sync_rx_buf_err); + ble_ll_event_send(&g_ble_ll_sync_sm_current->sync_ev_end); + } + + /* PHY is disabled here */ + ble_ll_sync_current_sm_over(); + + return 1; +} + +/** + * Called when the wait for response timer expires while in the sync state. + * + * Context: Interrupt. + */ +void +ble_ll_sync_wfr_timer_exp(void) +{ + struct ble_ll_sync_sm *sm = g_ble_ll_sync_sm_current; + + BLE_LL_ASSERT(g_ble_ll_sync_sm_current); + STATS_INC(ble_ll_stats, sync_missed_err); + + ble_ll_sync_current_sm_over(); + ble_ll_event_send(&sm->sync_ev_end); +} + +/** + * Called when sync event needs to be halted. This normally should not be called + * and is only called when a scheduled item executes but scanning for sync/chain + * is stil ongoing + * Context: Interrupt + */ +void +ble_ll_sync_halt(void) +{ + struct ble_ll_sync_sm *sm = g_ble_ll_sync_sm_current; + + ble_ll_sync_current_sm_over(); + + if (sm) { + ble_ll_event_send(&sm->sync_ev_end); + } +} + +uint32_t +ble_ll_sync_get_event_end_time(void) +{ + uint32_t end_time; + + if (g_ble_ll_sync_sm_current) { + end_time = g_ble_ll_sync_sm_current->sch.end_time; + } else { + end_time = os_cputime_get32(); + } + return end_time; +} + +static uint8_t +ble_ll_sync_phy_mode_to_aux_phy(uint8_t phy_mode) +{ + switch (phy_mode) { + case BLE_PHY_MODE_1M: + return 0x00; + case BLE_PHY_MODE_2M: + return 0x01; + case BLE_PHY_MODE_CODED_125KBPS: + case BLE_PHY_MODE_CODED_500KBPS: + return 0x02; + default: + BLE_LL_ASSERT(false); + return 0x00; + } +} + +static void +ble_ll_sync_parse_aux_ptr(const uint8_t *buf, uint8_t *chan, uint32_t *offset, + uint8_t *offset_units, uint8_t *phy) +{ + uint32_t aux_ptr_field = get_le32(buf) & 0x00FFFFFF; + + *chan = aux_ptr_field & 0x3F; + + /* TODO use CA aux_ptr_field >> 6 */ + + if ((aux_ptr_field >> 7) & 0x01) { + *offset = 300 * ((aux_ptr_field >> 8) & 0x1FFF); + *offset_units = 1; + } else { + *offset = 30 * ((aux_ptr_field >> 8) & 0x1FFF); + *offset_units = 0; + } + + *phy = (aux_ptr_field >> 21) & 0x07; +} + +static int +ble_ll_sync_chain_start_cb(struct ble_ll_sched_item *sch) +{ + struct ble_ll_sync_sm *sm; + uint32_t wfr_usecs; + uint32_t start; + int rc; + + /* Set current connection state machine */ + sm = sch->cb_arg; + g_ble_ll_sync_sm_current = sm; + BLE_LL_ASSERT(sm); + + /* Disable whitelisting */ + ble_ll_whitelist_disable(); + + /* Set LL state */ + ble_ll_state_set(BLE_LL_STATE_SYNC); + + /* Set channel */ + ble_phy_setchan(sm->chan_chain, sm->access_addr, sm->crcinit); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + ble_phy_resolv_list_disable(); +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + ble_phy_encrypt_disable(); +#endif + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + ble_phy_mode_set(sm->phy_mode, sm->phy_mode); +#endif + + start = sch->start_time + g_ble_ll_sched_offset_ticks; + rc = ble_phy_rx_set_start_time(start, sch->remainder); + if (rc && rc != BLE_PHY_ERR_RX_LATE) { + STATS_INC(ble_ll_stats, sync_chain_failed); + rc = BLE_LL_SCHED_STATE_DONE; + ble_ll_event_send(&sm->sync_ev_end); + ble_ll_sync_current_sm_over(); + } else { + /* + * Clear flag that tells to set last anchor point if a packet + * has been received, this is chain and we don't need it. + */ + sm->flags &= ~BLE_LL_SYNC_SM_FLAG_SET_ANCHOR; + + wfr_usecs = (sm->flags & BLE_LL_SYNC_SM_FLAG_OFFSET_300) ? 300 : 30; + + ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_RX, 0, wfr_usecs); + rc = BLE_LL_SCHED_STATE_RUNNING; + } + + return rc; +} + +static int +ble_ll_sync_schedule_chain(struct ble_ll_sync_sm *sm, struct ble_mbuf_hdr *hdr, + const uint8_t *aux) +{ + uint8_t offset_units; + uint32_t offset; + uint8_t chan; + uint8_t phy; + + ble_ll_sync_parse_aux_ptr(aux, &chan, &offset, &offset_units, &phy); + + if (chan >= BLE_PHY_NUM_DATA_CHANS) { + return -1; + } + + if (offset < BLE_LL_MAFS) { + return -1; + } + + /* chain should use same PHY as master PDU */ + if (phy != ble_ll_sync_phy_mode_to_aux_phy(sm->phy_mode)) { + return -1; + } + + if (offset_units) { + sm->flags |= BLE_LL_SYNC_SM_FLAG_OFFSET_300; + } else { + sm->flags &= ~BLE_LL_SYNC_SM_FLAG_OFFSET_300; + } + + sm->chan_chain = chan; + + sm->sch.sched_cb = ble_ll_sync_chain_start_cb; + sm->sch.cb_arg = sm; + sm->sch.sched_type = BLE_LL_SCHED_TYPE_SYNC; + + return ble_ll_sched_sync(&sm->sch, hdr->beg_cputime, hdr->rem_usecs, + offset, sm->phy_mode); +} + +static void +ble_ll_sync_established(struct ble_ll_sync_sm *sm) +{ + BLE_LL_ASSERT(sm->sync_pending_cnt); + + /* mark as established */ + + sm->flags |= BLE_LL_SYNC_SM_FLAG_ESTABLISHED; + sm->flags &= ~BLE_LL_SYNC_SM_FLAG_ESTABLISHING; + + sm->sync_pending_cnt = 0; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) + if (sm->transfer_conn) { + ble_ll_sync_transfer_received(sm, BLE_ERR_SUCCESS); + return; + } +#endif + + ble_ll_sync_est_event_success(sm); +} + +static void +ble_ll_sync_check_failed(struct ble_ll_sync_sm *sm) +{ + BLE_LL_ASSERT(sm->sync_pending_cnt); + + /* if we can retry on next event */ + if (--sm->sync_pending_cnt) { + return; + } + + sm->flags &= ~BLE_LL_SYNC_SM_FLAG_ESTABLISHING; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) + if (sm->transfer_conn) { + ble_ll_sync_transfer_received(sm, BLE_ERR_CONN_ESTABLISHMENT); + return; + } +#endif + + ble_ll_sync_est_event_failed(BLE_ERR_CONN_ESTABLISHMENT); +} + +void +ble_ll_sync_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr) +{ + struct ble_ll_sync_sm *sm = hdr->rxinfo.user_data; + bool aux_scheduled = false; + int8_t tx_power = 127; /* defaults to not available */ + uint8_t *aux = NULL; + int datalen; + + BLE_LL_ASSERT(sm); + + /* this could happen if sync was cancelled or terminated while pkt_in was + * already in LL queue, just drop in that case + */ + if (!sm->flags) { + ble_ll_scan_chk_resume(); + ble_ll_rfmgmt_release(); + return; + } + + /* Set anchor point (and last) if 1st rxd frame in sync event. + * According to spec this should be done even if CRC is not valid so we + * can store it here + */ + if (sm->flags & BLE_LL_SYNC_SM_FLAG_SET_ANCHOR) { + sm->flags &= ~BLE_LL_SYNC_SM_FLAG_SET_ANCHOR; + + sm->anchor_point = hdr->beg_cputime; + sm->anchor_point_usecs = hdr->rem_usecs; + sm->last_anchor_point = sm->anchor_point; + } + + /* CRC error, end event */ + if (!BLE_MBUF_HDR_CRC_OK(hdr)) { + STATS_INC(ble_ll_stats, sync_crc_err); + goto end_event; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) + /* save last pa counter */ + sm->event_cntr_last_received = sm->event_cntr; +#endif + + /* this means we are chaining but due to low buffers already sent data + * truncated report to host (or didn't sent any at all). If this happens + * next_buf should be already set to NULL and we just end event. + */ + if (sm->flags & BLE_LL_SYNC_SM_FLAG_HCI_TRUNCATED) { + BLE_LL_ASSERT(!sm->next_report); + goto end_event; + } + + if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT) && + !(sm->flags & BLE_LL_SYNC_SM_FLAG_DISABLED)) { + /* get ext header data */ + datalen = ble_ll_sync_parse_ext_hdr(rxpdu, &aux, &tx_power); + if (datalen < 0) { + /* we got bad packet, end event */ + goto end_event; + } + + /* if aux is present, we need to schedule ASAP */ + if (aux && (ble_ll_sync_schedule_chain(sm, hdr, aux) == 0)) { + aux_scheduled = true; + } + + /* in case data reporting is enabled we need to send sync established here */ + if (sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING) { + ble_ll_sync_established(sm); + } + + /* Adjust rxpdu to contain advertising data only */ + ble_ll_sync_adjust_ext_hdr(rxpdu); + + /* send reports from this PDU */ + ble_ll_sync_send_per_adv_rpt(sm, rxpdu, hdr->rxinfo.rssi, tx_power, + datalen, aux, aux_scheduled); + } else { + /* we need to establish link even if reporting was disabled */ + if (sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING) { + ble_ll_sync_established(sm); + } + } + + /* if chain was scheduled we don't end event yet */ + /* TODO should we check resume only if offset is high? */ + if (aux_scheduled) { + ble_ll_scan_chk_resume(); + ble_ll_rfmgmt_release(); + return; + } + +end_event: + ble_ll_event_send(&sm->sync_ev_end); + ble_ll_rfmgmt_release(); +} + +static int +ble_ll_sync_next_event(struct ble_ll_sync_sm *sm, uint32_t cur_ww_adjust) +{ + uint32_t cur_ww; + uint32_t max_ww; + uint32_t ticks; + uint32_t itvl; + uint8_t usecs; + uint16_t skip = sm->skip; + + /* don't skip if are establishing sync or we missed last event */ + if (skip && ((sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING) || + CPUTIME_LT(sm->last_anchor_point, sm->anchor_point))) { + skip = 0; + } + + /* Set next event start time, we can use pre-calculated values for one + * interval if not skipping + */ + if (skip == 0) { + ticks = sm->itvl_ticks; + usecs = sm->itvl_usecs; + } else { + itvl = sm->itvl * BLE_LL_SYNC_ITVL_USECS * (1 + skip); + ticks = os_cputime_usecs_to_ticks(itvl); + usecs = itvl - os_cputime_ticks_to_usecs(ticks); + } + + sm->anchor_point += ticks; + sm->anchor_point_usecs += usecs; + if (sm->anchor_point_usecs >= 31) { + sm->anchor_point++; + sm->anchor_point_usecs -= 31; + } + + /* Set event counter to the next event */ + sm->event_cntr += 1 + skip; + + /* Calculate channel index of next event */ + sm->chan_index = ble_ll_utils_calc_dci_csa2(sm->event_cntr, sm->channel_id, + sm->num_used_chans, sm->chanmap); + + cur_ww = ble_ll_utils_calc_window_widening(sm->anchor_point, + sm->last_anchor_point, + sm->sca); + + cur_ww += cur_ww_adjust; + + max_ww = (sm->itvl * (BLE_LL_SYNC_ITVL_USECS / 2)) - BLE_LL_IFS; + if (cur_ww >= max_ww) { + return -1; + } + + cur_ww += BLE_LL_JITTER_USECS; + + /* if updated anchor is pass last anchor + timeout it means we will not be + * able to get it in time and hit sync timeout + * + * note that this may result in sync timeout being sent before real + * timeout but we won't be able to fit in time anyway.. + * + * We don't do that when establishing since we try up to + * BLE_LL_SYNC_ESTABLISH_CNT events before failing regardless of timeout + */ + if (!(sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING)) { + if (CPUTIME_GT(sm->anchor_point - os_cputime_usecs_to_ticks(cur_ww), + sm->last_anchor_point + sm->timeout )) { + return -1; + } + } + + sm->window_widening = cur_ww; + + return 0; +} + +static void +ble_ll_sync_event_end(struct ble_npl_event *ev) +{ + struct ble_ll_sync_sm *sm; + + /* Better be a connection state machine! */ + sm = ble_npl_event_get_arg(ev); + BLE_LL_ASSERT(sm); + + ble_ll_rfmgmt_release(); + + if (sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING) { + ble_ll_sync_check_failed(sm); + } + + /* Check if we need to resume scanning */ + ble_ll_scan_chk_resume(); + + /* Remove any end events that might be enqueued */ + ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &sm->sync_ev_end); + + /* don't schedule next event if sync is not established nor establishing + * at this point SM is no longer valid + */ + if (!(sm->flags & (BLE_LL_SYNC_SM_FLAG_ESTABLISHED | + BLE_LL_SYNC_SM_FLAG_ESTABLISHING))) { + ble_ll_sync_sm_clear(sm); + return; + } + + /* if we had prepared buffer for next even it means we were chaining and + * must send truncated report to host + */ + if (sm->next_report) { + BLE_LL_ASSERT(!(sm->flags & BLE_LL_SYNC_SM_FLAG_HCI_TRUNCATED)); + ble_ll_sync_send_truncated_per_adv_rpt(sm, sm->next_report); + sm->next_report = NULL; + } + + /* Event ended so we are no longer chaining */ + sm->flags &= ~BLE_LL_SYNC_SM_FLAG_HCI_TRUNCATED; + + sm->sch.sched_cb = ble_ll_sync_event_start_cb; + sm->sch.cb_arg = sm; + sm->sch.sched_type = BLE_LL_SCHED_TYPE_SYNC; + + do { + if (ble_ll_sync_next_event(sm, 0) < 0) { + if (sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING) { + /* don't allow any retry if this failed */ + sm->sync_pending_cnt = 1; + ble_ll_sync_check_failed(sm); + } else { + ble_ll_sync_lost_event(sm); + } + + /* at this point SM is no longer valid */ + ble_ll_sync_sm_clear(sm); + return; + } + } while (ble_ll_sched_sync_reschedule(&sm->sch, sm->anchor_point, + sm->anchor_point_usecs, + sm->window_widening, sm->phy_mode)); +} + +void +ble_ll_sync_info_event(const uint8_t *addr, uint8_t addr_type, int rpa_index, + uint8_t sid, struct ble_mbuf_hdr *rxhdr, + const uint8_t *syncinfo) +{ + struct ble_ll_sync_sm *sm = NULL; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) + const uint8_t *rpa = NULL; +#endif + uint16_t max_skip; + uint32_t offset; + uint32_t usecs; + uint16_t itvl; + int i; + + /* ignore if not synchronizing */ + if (!g_ble_ll_sync_create_comp_ev) { + return; + } + + /* get reserved SM */ + for (i = 0; i < BLE_LL_SYNC_CNT; i++) { + if (g_ble_ll_sync_sm[i].flags & BLE_LL_SYNC_SM_FLAG_RESERVED) { + sm = &g_ble_ll_sync_sm[i]; + break; + } + } + + /* this means we already got sync info event and pending sync */ + if (!sm) { + return; + } + + /* check if resolved */ + if (rpa_index >= 0) { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) + rpa = addr; +#endif + addr = g_ble_ll_resolv_list[rpa_index].rl_identity_addr; + addr_type = g_ble_ll_resolv_list[rpa_index].rl_addr_type; + } + + /* check peer */ + if (g_ble_ll_sync_create_params.options & BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_FILTER) { + if (ble_ll_sync_on_list(addr, addr_type, sid) < 0) { + return; + } + + /* set addr and sid in sm */ + sm->adv_sid = sid; + sm->adv_addr_type = addr_type; + memcpy(sm->adv_addr, addr, BLE_DEV_ADDR_LEN); + } else { + if ((sm->adv_sid != sid) || (sm->adv_addr_type != addr_type) || + memcmp(sm->adv_addr, addr, BLE_DEV_ADDR_LEN)) { + return; + } + } + + /* Sync Packet Offset (13 bits), Offset Units (1 bit), RFU (2 bits) */ + offset = syncinfo[0]; + offset |= (uint16_t)(syncinfo[1] & 0x1f) << 8; + + /* ignore if offset is not valid */ + if (!offset) { + return; + } + + /* Interval (2 bytes), ignore if invalid */ + itvl = get_le16(&syncinfo[2]); + if (itvl < 6) { + return; + } + + if (rpa_index >= 0) { + sm->flags |= BLE_LL_SYNC_SM_FLAG_ADDR_RESOLVED; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) + memcpy(sm->adv_addr_rpa, rpa, BLE_DEV_ADDR_LEN); +#endif + } + + /* set params from HCI LE Create Periodic Sync */ + sm->timeout = g_ble_ll_sync_create_params.timeout; + sm->skip = g_ble_ll_sync_create_params.max_skip; + sm->sync_pending_cnt = BLE_LL_SYNC_ESTABLISH_CNT; + + if (syncinfo[1] & 0x20) { + offset *= 300; + sm->flags |= BLE_LL_SYNC_SM_FLAG_OFFSET_300; + } else { + offset *= 30; + sm->flags &= ~BLE_LL_SYNC_SM_FLAG_OFFSET_300; + } + + /* sync end event */ + ble_npl_event_init(&sm->sync_ev_end, ble_ll_sync_event_end, sm); + + sm->itvl = itvl; + + /* precalculate interval ticks and usecs */ + usecs = sm->itvl * BLE_LL_SYNC_ITVL_USECS; + sm->itvl_ticks = os_cputime_usecs_to_ticks(usecs); + sm->itvl_usecs = (uint8_t)(usecs - + os_cputime_ticks_to_usecs(sm->itvl_ticks)); + if (sm->itvl_usecs == 31) { + sm->itvl_usecs = 0; + sm->itvl_ticks++; + } + + /* Channels Mask (37 bits) */ + sm->chanmap[0] = syncinfo[4]; + sm->chanmap[1] = syncinfo[5]; + sm->chanmap[2] = syncinfo[6]; + sm->chanmap[3] = syncinfo[7]; + sm->chanmap[4] = syncinfo[8] & 0x1f; + sm->num_used_chans = ble_ll_utils_calc_num_used_chans(sm->chanmap); + + /* SCA (3 bits) */ + sm->sca = syncinfo[8] >> 5; + + /* AA (4 bytes) */ + sm->access_addr = get_le32(&syncinfo[9]); + sm->channel_id = ((sm->access_addr & 0xffff0000) >> 16) ^ + (sm->access_addr & 0x0000ffff); + + /* CRCInit (3 bytes) */ + sm->crcinit = syncinfo[15]; + sm->crcinit = (sm->crcinit << 8) | syncinfo[14]; + sm->crcinit = (sm->crcinit << 8) | syncinfo[13]; + + /* Event Counter (2 bytes) */ + sm->event_cntr = get_le16(&syncinfo[16]); + + /* adjust skip if pass timeout */ + max_skip = get_max_skip(sm->itvl * BLE_LL_SYNC_ITVL_USECS, sm->timeout); + if (sm->skip > max_skip) { + sm->skip = max_skip; + } + + /* from now on we only need timeout in ticks */ + sm->timeout = os_cputime_usecs_to_ticks(sm->timeout); + + sm->phy_mode = rxhdr->rxinfo.phy_mode; + sm->window_widening = BLE_LL_JITTER_USECS; + + /* Calculate channel index of first event */ + sm->chan_index = ble_ll_utils_calc_dci_csa2(sm->event_cntr, sm->channel_id, + sm->num_used_chans, sm->chanmap); + + sm->sch.sched_cb = ble_ll_sync_event_start_cb; + sm->sch.cb_arg = sm; + sm->sch.sched_type = BLE_LL_SCHED_TYPE_SYNC; + + if (ble_ll_sched_sync(&sm->sch, rxhdr->beg_cputime, rxhdr->rem_usecs, + offset, sm->phy_mode)) { + return; + } + + sm->anchor_point = sm->sch.start_time + g_ble_ll_sched_offset_ticks; + sm->anchor_point_usecs = sm->sch.remainder; + sm->last_anchor_point = sm->anchor_point; + +#if MYNEWT_VAL(BLE_VERSION) >= 51 + if (g_ble_ll_sync_create_params.options & BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_DISABLED) { + sm->flags |= BLE_LL_SYNC_SM_FLAG_DISABLED; + } +#endif + + sm->flags &= ~BLE_LL_SYNC_SM_FLAG_RESERVED; + sm->flags |= BLE_LL_SYNC_SM_FLAG_ESTABLISHING; + sm->flags |= BLE_LL_SYNC_SM_FLAG_SYNC_INFO; +} + +static struct ble_ll_sync_sm * +ble_ll_sync_reserve(void) +{ + struct ble_ll_sync_sm *sm; + int i; + + for (i = 0; i < BLE_LL_SYNC_CNT; i++) { + sm = &g_ble_ll_sync_sm[i]; + + if (!sm->flags) { + sm->flags |= BLE_LL_SYNC_SM_FLAG_RESERVED; + return sm; + } + } + + return NULL; +} + +int +ble_ll_sync_create(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_periodic_adv_create_sync_cp *cmd = (const void *) cmdbuf; + struct ble_ll_sync_sm *sm; + uint16_t timeout; + os_sr_t sr; + + if (g_ble_ll_sync_create_comp_ev) { + return BLE_ERR_CMD_DISALLOWED; + } + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + +#if MYNEWT_VAL(BLE_VERSION) >= 51 + if (cmd->options > BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_DISABLED) { +#else + if (cmd->options > BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_FILTER) { +#endif + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (cmd->skip > 0x01f3) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + timeout = le16toh(cmd->sync_timeout); + if (timeout < 0x000a || timeout > 0x4000) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + +#if MYNEWT_VAL(BLE_VERSION) >= 51 + /* we don't support any CTE yet */ + if (cmd->sync_cte_type) { + if (cmd->sync_cte_type > 4) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + return BLE_ERR_UNSUPPORTED; + } +#endif + + if (cmd->options & BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_FILTER) { + if (ble_ll_sync_list_empty()) { + return BLE_ERR_CMD_DISALLOWED; + } + } else { + if (cmd->sid > 0x0f) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (cmd->peer_addr_type > BLE_HCI_ADV_PEER_ADDR_MAX) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + OS_ENTER_CRITICAL(sr); + sm = ble_ll_sync_find(cmd->peer_addr, cmd->peer_addr_type, cmd->sid); + OS_EXIT_CRITICAL(sr); + + if (sm) { + return BLE_ERR_ACL_CONN_EXISTS; + } + } + + /* reserve buffer for sync complete event */ + g_ble_ll_sync_create_comp_ev = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (!g_ble_ll_sync_create_comp_ev) { + return BLE_ERR_MEM_CAPACITY; + } + + OS_ENTER_CRITICAL(sr); + + /* reserve 1 SM for created sync */ + sm = ble_ll_sync_reserve(); + if (!sm) { + ble_hci_trans_buf_free(g_ble_ll_sync_create_comp_ev); + g_ble_ll_sync_create_comp_ev = NULL; + OS_EXIT_CRITICAL(sr); + return BLE_ERR_MEM_CAPACITY; + } + + /* if we don't use list, store expected address in reserved SM */ + if (!(cmd->options & BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_FILTER)) { + sm->adv_sid = cmd->sid; + sm->adv_addr_type = cmd->peer_addr_type; + memcpy(&sm->adv_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN); + } + + g_ble_ll_sync_create_params.timeout = timeout * 10000; /* 10ms units, store in us */; + g_ble_ll_sync_create_params.max_skip = cmd->skip; + g_ble_ll_sync_create_params.options = cmd->options; + + OS_EXIT_CRITICAL(sr); + return BLE_ERR_SUCCESS; +} + +static void +ble_ll_sync_cancel_complete_event(void) +{ + ble_ll_sync_est_event_failed(BLE_ERR_OPERATION_CANCELLED); +} + +int +ble_ll_sync_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb) +{ + struct ble_ll_sync_sm *sm; + os_sr_t sr; + int i; + + if (!g_ble_ll_sync_create_comp_ev) { + return BLE_ERR_CMD_DISALLOWED; + } + + OS_ENTER_CRITICAL(sr); + + for (i = 0; i < BLE_LL_SYNC_CNT; i++) { + sm = &g_ble_ll_sync_sm[i]; + + /* cancelled before fist sync info packet */ + if (sm->flags & BLE_LL_SYNC_SM_FLAG_RESERVED) { + memset(sm, 0, sizeof(*sm)); + break; + } + + /* cancelled while pending sync */ + if (sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING) { + ble_ll_sync_sm_clear(sm); + break; + } + } + + OS_EXIT_CRITICAL(sr); + + /* g_ble_ll_sync_create_comp_ev will be cleared by this callback */ + *post_cmd_cb = ble_ll_sync_cancel_complete_event; + + return BLE_ERR_SUCCESS; +} + +int +ble_ll_sync_terminate(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_periodic_adv_term_sync_cp *cmd = (const void *) cmdbuf; + struct ble_ll_sync_sm *sm; + uint16_t handle; + os_sr_t sr; + + if (g_ble_ll_sync_create_comp_ev) { + return BLE_ERR_CMD_DISALLOWED; + } + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + handle = le16toh(cmd->sync_handle); + if (handle > 0xeff) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (handle >= BLE_LL_SYNC_CNT) { + return BLE_ERR_UNK_ADV_INDENT; + } + + sm = &g_ble_ll_sync_sm[handle]; + + OS_ENTER_CRITICAL(sr); + + if (!(sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHED)) { + OS_EXIT_CRITICAL(sr); + return BLE_ERR_UNK_ADV_INDENT; + } + + ble_ll_sync_sm_clear(sm); + + OS_EXIT_CRITICAL(sr); + + return BLE_ERR_SUCCESS; +} + +int +ble_ll_sync_list_add(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_add_dev_to_periodic_adv_list_cp *cmd = (const void *)cmdbuf; + int i; + + if (g_ble_ll_sync_create_comp_ev) { + return BLE_ERR_CMD_DISALLOWED; + } + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (cmd->peer_addr_type > BLE_HCI_ADV_PEER_ADDR_MAX) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + if (cmd->sid > 0x0f) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + i = ble_ll_sync_on_list(cmd->peer_addr, cmd->peer_addr_type, cmd->sid); + if (i >= 0) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + i = ble_ll_sync_list_get_free(); + if (i < 0) { + return BLE_ERR_MEM_CAPACITY; + } + + g_ble_ll_sync_adv_list[i].adv_sid = cmd->sid; + g_ble_ll_sync_adv_list[i].adv_addr_type = cmd->peer_addr_type; + memcpy(&g_ble_ll_sync_adv_list[i].adv_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN); + + return BLE_ERR_SUCCESS; +} + +int +ble_ll_sync_list_remove(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_rem_dev_from_periodic_adv_list_cp *cmd = (const void *)cmdbuf; + int i; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (g_ble_ll_sync_create_comp_ev) { + return BLE_ERR_CMD_DISALLOWED; + } + + if (cmd->peer_addr_type > BLE_HCI_ADV_PEER_ADDR_MAX) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (cmd->sid > 0x0f) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + i = ble_ll_sync_on_list(cmd->peer_addr, cmd->peer_addr_type, cmd->sid); + if (i < 0) { + return BLE_ERR_UNK_ADV_INDENT; + } + + memset(&g_ble_ll_sync_adv_list[i], 0, sizeof(g_ble_ll_sync_adv_list[i])); + g_ble_ll_sync_adv_list[i].adv_sid = 0xff; + + return BLE_ERR_SUCCESS; +} + +int +ble_ll_sync_list_clear(void) +{ + int i; + + if (g_ble_ll_sync_create_comp_ev) { + return BLE_ERR_CMD_DISALLOWED; + } + + for (i = 0; i < ARRAY_SIZE(g_ble_ll_sync_adv_list); i++) { + memset(&g_ble_ll_sync_adv_list[i], 0, sizeof(g_ble_ll_sync_adv_list[i])); + g_ble_ll_sync_adv_list[i].adv_sid = 0xff; + } + + return BLE_ERR_SUCCESS; +} + +int +ble_ll_sync_list_size(uint8_t *rspbuf, uint8_t *rsplen) +{ + struct ble_hci_le_rd_periodic_adv_list_size_rp *rsp = (void *) rspbuf; + + rsp->list_size = ARRAY_SIZE(g_ble_ll_sync_adv_list); + + *rsplen = sizeof(*rsp); + return BLE_ERR_SUCCESS; +} + +#if MYNEWT_VAL(BLE_VERSION) >= 51 +int +ble_ll_sync_receive_enable(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_periodic_adv_receive_enable_cp *cmd = (const void *)cmdbuf; + struct ble_ll_sync_sm *sm; + uint16_t handle; + os_sr_t sr; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (cmd->enable > 0x01) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + handle = le16toh(cmd->sync_handle); + if (handle > 0xeff) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (handle >= BLE_LL_SYNC_CNT) { + return BLE_ERR_UNK_ADV_INDENT; + } + + sm = &g_ble_ll_sync_sm[handle]; + + OS_ENTER_CRITICAL(sr); + + if (!(sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHED)) { + OS_EXIT_CRITICAL(sr); + return BLE_ERR_UNK_ADV_INDENT; + } + + if (cmd->enable) { + sm->flags &= ~BLE_LL_SYNC_SM_FLAG_DISABLED; + } else { + sm->flags |= BLE_LL_SYNC_SM_FLAG_DISABLED; + } + + OS_EXIT_CRITICAL(sr); + return BLE_ERR_SUCCESS; +} +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) +static struct ble_ll_sync_sm * +ble_ll_sync_transfer_get(const uint8_t *addr, uint8_t addr_type, uint8_t sid) +{ + struct ble_ll_sync_sm *sm; + int i; + + for (i = 0; i < BLE_LL_SYNC_CNT; i++) { + sm = &g_ble_ll_sync_sm[i]; + + if (!sm->flags) { + /* allocate event for transfer received event */ + sm->transfer_received_ev = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (!sm->transfer_received_ev) { + break; + } + + sm->adv_sid = sid; + sm->adv_addr_type = addr_type; + memcpy(&sm->adv_addr, addr, BLE_DEV_ADDR_LEN); + + sm->flags |= BLE_LL_SYNC_SM_FLAG_ESTABLISHING; + return sm; + } + } + + return NULL; +} + +void +ble_ll_sync_periodic_ind(struct ble_ll_conn_sm *connsm, + const uint8_t *sync_ind, bool reports_disabled, + uint16_t max_skip, uint32_t sync_timeout) +{ + const uint8_t *syncinfo = sync_ind + 2; + uint16_t sync_conn_event_count; + uint16_t last_pa_event_count; + struct ble_ll_sync_sm *sm; + uint16_t conn_event_count; + uint8_t sync_anchor_usecs; + const uint8_t *rpa = NULL; + int last_pa_diff; + uint32_t sync_anchor; + const uint8_t *addr; + uint16_t event_cntr; + uint32_t itvl_usecs; + uint32_t ww_adjust; + uint8_t addr_type; + uint8_t phy_mode; + uint32_t offset; + uint32_t future; + uint16_t itvl; + int rpa_index; + uint8_t sid; + uint8_t sca; + os_sr_t sr; + + phy_mode = ble_ll_ctrl_phy_from_phy_mask(sync_ind[25]); + itvl = get_le16(syncinfo + 2); + /* ignore if sync params are not valid */ + if ((phy_mode == 0) || (itvl < 6)) { + return; + } + + last_pa_event_count = get_le16(sync_ind + 22); + event_cntr = get_le16(syncinfo + 16); + itvl_usecs = itvl * BLE_LL_SYNC_ITVL_USECS; + + last_pa_diff = abs((int16_t)(event_cntr - last_pa_event_count)); + /* check if not 5 seconds apart, if so ignore sync transfer */ + if ((last_pa_diff * itvl_usecs) > 5000000) { + return; + } + + sid = (sync_ind[24] & 0x0f); + addr_type = (sync_ind[24] & 0x10) ? BLE_ADDR_RANDOM : BLE_ADDR_PUBLIC; + addr = sync_ind + 26; + + rpa_index = -1; + + /* check if need to resolve */ + if (ble_ll_is_rpa(addr, addr_type)) { + rpa_index = ble_ll_resolv_peer_rpa_any(addr); + if (rpa_index >= 0) { + rpa = addr; + addr = g_ble_ll_resolv_list[rpa_index].rl_identity_addr; + addr_type = g_ble_ll_resolv_list[rpa_index].rl_addr_type; + } + } + + OS_ENTER_CRITICAL(sr); + /* check if already synchronized with this peer */ + sm = ble_ll_sync_find(addr, addr_type, sid); + if (sm) { + OS_EXIT_CRITICAL(sr); + return; + } + + /* ignore if no memory for new sync */ + sm = ble_ll_sync_transfer_get(addr, addr_type, sid); + if (!sm) { + OS_EXIT_CRITICAL(sr); + return; + } + + OS_EXIT_CRITICAL(sr); + + if (rpa_index >= 0) { + sm->flags |= BLE_LL_SYNC_SM_FLAG_ADDR_RESOLVED; + memcpy(sm->adv_addr_rpa, rpa, BLE_DEV_ADDR_LEN); + } + + /* set params from transfer */ + sm->timeout = os_cputime_usecs_to_ticks(sync_timeout); + sm->skip = max_skip; + sm->sync_pending_cnt = BLE_LL_SYNC_ESTABLISH_CNT; + sm->transfer_id = get_le16(sync_ind); /* first two bytes */ + sm->transfer_conn = connsm; + + /* Sync Packet Offset (13 bits), Offset Units (1 bit), Offset Adjust (1 bit), + * RFU (1 bit) + */ + offset = syncinfo[0]; + offset |= (uint16_t)(syncinfo[1] & 0x1f) << 8; + + if (syncinfo[1] & 0x20) { + if (syncinfo[1] & 0x40) { + offset += 0x2000; + } + + offset *= 300; + sm->flags |= BLE_LL_SYNC_SM_FLAG_OFFSET_300; + } else { + offset *= 30; + sm->flags &= ~BLE_LL_SYNC_SM_FLAG_OFFSET_300; + } + + /* sync end event */ + ble_npl_event_init(&sm->sync_ev_end, ble_ll_sync_event_end, sm); + + sm->itvl = itvl; + + /* precalculate interval ticks and usecs */ + sm->itvl_ticks = os_cputime_usecs_to_ticks(itvl_usecs); + sm->itvl_usecs = (uint8_t)(itvl_usecs - + os_cputime_ticks_to_usecs(sm->itvl_ticks)); + if (sm->itvl_usecs == 31) { + sm->itvl_usecs = 0; + sm->itvl_ticks++; + } + + /* Channels Mask (37 bits) */ + sm->chanmap[0] = syncinfo[4]; + sm->chanmap[1] = syncinfo[5]; + sm->chanmap[2] = syncinfo[6]; + sm->chanmap[3] = syncinfo[7]; + sm->chanmap[4] = syncinfo[8] & 0x1f; + sm->num_used_chans = ble_ll_utils_calc_num_used_chans(sm->chanmap); + + /* SCA (3 bits) */ + sm->sca = syncinfo[8] >> 5; + + /* AA (4 bytes) */ + sm->access_addr = get_le32(syncinfo + 9); + sm->channel_id = ((sm->access_addr & 0xffff0000) >> 16) ^ + (sm->access_addr & 0x0000ffff); + + /* CRCInit (3 bytes) */ + sm->crcinit = syncinfo[13]; + sm->crcinit |= syncinfo[14] << 8; + sm->crcinit |= syncinfo[15] << 16; + + /* Event Counter (2 bytes) */ + sm->event_cntr = event_cntr; + + /* adjust skip if pass timeout */ + max_skip = get_max_skip(sm->itvl * BLE_LL_SYNC_ITVL_USECS, sync_timeout); + if (sm->skip > max_skip) { + sm->skip = max_skip; + } + + sm->phy_mode = phy_mode; + + /* Calculate channel index of first event */ + sm->chan_index = ble_ll_utils_calc_dci_csa2(sm->event_cntr, sm->channel_id, + sm->num_used_chans, sm->chanmap); + + sm->sch.sched_cb = ble_ll_sync_event_start_cb; + sm->sch.cb_arg = sm; + sm->sch.sched_type = BLE_LL_SCHED_TYPE_SYNC; + + /* get anchor for specified conn event */ + conn_event_count = get_le16(sync_ind + 20); + ble_ll_conn_get_anchor(connsm, conn_event_count, &sm->anchor_point, + &sm->anchor_point_usecs); + + /* Set last anchor point */ + sm->last_anchor_point = sm->anchor_point - (last_pa_diff * sm->itvl_ticks); + + /* calculate extra window widening */ + sync_conn_event_count = get_le16(sync_ind + 32); + sca = sync_ind[24] >> 5; + ble_ll_conn_get_anchor(connsm, sync_conn_event_count, &sync_anchor, + &sync_anchor_usecs); + ww_adjust = ble_ll_utils_calc_window_widening(connsm->anchor_point, + sync_anchor, sca); + + /* spin until we get anchor in future */ + future = os_cputime_get32() + g_ble_ll_sched_offset_ticks; + while (CPUTIME_LT(sm->anchor_point, future)) { + if (ble_ll_sync_next_event(sm, ww_adjust) < 0) { + /* release SM if this failed */ + ble_ll_sync_transfer_received(sm, BLE_ERR_CONN_ESTABLISHMENT); + memset(sm, 0, sizeof(*sm)); + return; + } + } + + if (ble_ll_sched_sync(&sm->sch, sm->anchor_point, sm->anchor_point_usecs, + offset, sm->phy_mode)) { + /* release SM if this failed */ + ble_ll_sync_transfer_received(sm, BLE_ERR_CONN_ESTABLISHMENT); + memset(sm, 0, sizeof(*sm)); + return; + } + + /* Set new anchor point */ + sm->anchor_point = sm->sch.start_time + g_ble_ll_sched_offset_ticks; + sm->anchor_point_usecs = sm->sch.remainder; + + if (reports_disabled) { + sm->flags |= BLE_LL_SYNC_SM_FLAG_DISABLED; + } +} + +static void +ble_ll_sync_put_syncinfo(struct ble_ll_sync_sm *syncsm, + struct ble_ll_conn_sm *connsm, uint8_t *conn_event_cnt, + uint8_t *dptr) +{ + uint8_t anchor_usecs; + uint16_t conn_cnt; + uint32_t offset; + uint32_t anchor; + uint8_t units; + + anchor = connsm->anchor_point; + anchor_usecs = connsm->anchor_point_usecs; + conn_cnt = connsm->event_cntr; + + /* get anchor for conn event that is before periodic_adv_event_start_time */ + while (CPUTIME_GT(anchor, syncsm->anchor_point)) { + ble_ll_conn_get_anchor(connsm, --conn_cnt, &anchor, &anchor_usecs); + } + + offset = os_cputime_ticks_to_usecs(syncsm->anchor_point - anchor); + offset -= anchor_usecs; + offset += syncsm->anchor_point_usecs; + + /* connEventCount */ + put_le16(conn_event_cnt, conn_cnt); + + /* Sync Packet Offset (13 bits), Offset Units (1 bit), Offset Adjust (1 bit), + * RFU (1 bit) + */ + if (offset > 245700) { + units = 0x20; + + if (offset >= 0x2000) { + offset -= 0x2000; + units |= 0x40; + } + + offset = offset / 300; + } else { + units = 0x00; + offset = offset / 30; + } + + dptr[0] = (offset & 0x000000ff); + dptr[1] = ((offset >> 8) & 0x0000001f) | units; + + /* Interval (2 bytes) */ + put_le16(&dptr[2], syncsm->itvl); + + /* Channels Mask (37 bits) */ + dptr[4] = syncsm->chanmap[0]; + dptr[5] = syncsm->chanmap[1]; + dptr[6] = syncsm->chanmap[2]; + dptr[7] = syncsm->chanmap[3]; + dptr[8] = syncsm->chanmap[4] & 0x1f; + + /* SCA (3 bits) */ + dptr[8] |= syncsm->sca << 5; + + /* AA (4 bytes) */ + put_le32(&dptr[9], syncsm->access_addr); + + /* CRCInit (3 bytes) */ + dptr[13] = (uint8_t)syncsm->crcinit; + dptr[14] = (uint8_t)(syncsm->crcinit >> 8); + dptr[15] = (uint8_t)(syncsm->crcinit >> 16); + + /* Event Counter (2 bytes) */ + put_le16(&dptr[16], syncsm->event_cntr); +} + +static int +ble_ll_sync_send_sync_ind(struct ble_ll_sync_sm *syncsm, + struct ble_ll_conn_sm *connsm, uint16_t service_data) +{ + struct os_mbuf *om; + uint8_t *sync_ind; + + om = os_msys_get_pkthdr(BLE_LL_CTRL_MAX_PDU_LEN, + sizeof(struct ble_mbuf_hdr)); + if (!om) { + return BLE_ERR_MEM_CAPACITY; + } + + om->om_data[0] = BLE_LL_CTRL_PERIODIC_SYNC_IND; + + sync_ind = om->om_data + 1; + + /* ID (service_data), already in LE order */ + memcpy(sync_ind, &service_data, sizeof(service_data)); + + /* fill in syncinfo */ + ble_ll_sync_put_syncinfo(syncsm, connsm, sync_ind + 20, sync_ind + 2); + + /* lastPaEventCounter */ + put_le16(sync_ind + 22, syncsm->event_cntr_last_received); + + /* SID, AType, SCA */ + sync_ind[24] = syncsm->adv_sid; + + if (syncsm->flags & BLE_LL_SYNC_SM_FLAG_ADDR_RESOLVED) { + sync_ind[24] |= 1 << 4; + } else { + sync_ind[24] |= (syncsm->adv_addr_type == BLE_ADDR_RANDOM) << 4 ; + } + + sync_ind[24] |= MYNEWT_VAL(BLE_LL_MASTER_SCA) << 5; + + /* PHY */ + sync_ind[25] = (0x01 << (ble_ll_sync_phy_mode_to_hci(syncsm->phy_mode) - 1)); + + /* AdvA */ + if (syncsm->flags & BLE_LL_SYNC_SM_FLAG_ADDR_RESOLVED) { + memcpy(sync_ind + 26, syncsm->adv_addr_rpa, BLE_DEV_ADDR_LEN); + } else { + memcpy(sync_ind + 26, syncsm->adv_addr, BLE_DEV_ADDR_LEN); + } + + /* syncConnEventCount */ + put_le16(sync_ind + 32, connsm->event_cntr); + + ble_ll_conn_enqueue_pkt(connsm, om, BLE_LL_LLID_CTRL, + BLE_LL_CTRL_PERIODIC_SYNC_IND_LEN + 1); + + return BLE_ERR_SUCCESS; +} + +int +ble_ll_sync_transfer(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_le_periodic_adv_sync_transfer_cp *cmd = (const void *)cmdbuf; + struct ble_hci_le_periodic_adv_sync_transfer_rp *rsp = (void *) rspbuf; + struct ble_ll_conn_sm *connsm; + struct ble_ll_sync_sm *sm; + uint16_t handle; + os_sr_t sr; + int rc; + + if (len != sizeof(*cmd)) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + + handle = le16toh(cmd->sync_handle); + if (handle > 0xeff) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + + if (handle >= BLE_LL_SYNC_CNT) { + rc = BLE_ERR_UNK_ADV_INDENT; + goto done; + } + + sm = &g_ble_ll_sync_sm[handle]; + + OS_ENTER_CRITICAL(sr); + + if (!(sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHED)) { + rc = BLE_ERR_UNK_ADV_INDENT; + OS_EXIT_CRITICAL(sr); + goto done; + } + + handle = le16toh(cmd->conn_handle); + if (handle > 0xeff) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + OS_EXIT_CRITICAL(sr); + goto done; + } + + connsm = ble_ll_conn_find_active_conn(handle); + if (!connsm) { + rc = BLE_ERR_UNK_CONN_ID; + OS_EXIT_CRITICAL(sr); + goto done; + } + + /* TODO should not need to shift + * byte 3 (0 byte is conn_feature) , bit 1 + * + * Allow initiate LL procedure only if remote supports it. + */ + if (!(connsm->remote_features[2] & (BLE_LL_FEAT_SYNC_TRANS_RECV >> (8 * 3)))) { + rc = BLE_ERR_UNSUPP_REM_FEATURE; + goto done; + } + + rc = ble_ll_sync_send_sync_ind(sm, connsm, cmd->service_data); + + OS_EXIT_CRITICAL(sr); +done: + rsp->conn_handle = cmd->conn_handle; + *rsplen = sizeof(*rsp); + return rc; +} +#endif + +/* + * Called when a sync scan event has been removed from the scheduler + * without being run. + */ +void +ble_ll_sync_rmvd_from_sched(struct ble_ll_sync_sm *sm) +{ + ble_ll_event_send(&sm->sync_ev_end); +} + +bool +ble_ll_sync_enabled(void) +{ + return g_ble_ll_sync_create_comp_ev != NULL; +} + +/** + * Called to reset the sync module. When this function is called the + * scheduler has been stopped and the phy has been disabled. The LL should + * be in the standby state. + */ +void +ble_ll_sync_reset(void) +{ + int i; + + for (i = 0; i < BLE_LL_SYNC_CNT; i++) { + ble_ll_sync_sm_clear(&g_ble_ll_sync_sm[i]); + } + + for (i = 0; i < ARRAY_SIZE(g_ble_ll_sync_adv_list); i++) { + memset(&g_ble_ll_sync_adv_list[i], 0, sizeof(g_ble_ll_sync_adv_list[i])); + g_ble_ll_sync_adv_list[i].adv_sid = 0xff; + } + + g_ble_ll_sync_create_params.timeout = 0; + g_ble_ll_sync_create_params.max_skip = 0; + g_ble_ll_sync_create_params.options = 0; + + g_ble_ll_sync_sm_current = NULL; + + if (g_ble_ll_sync_create_comp_ev) { + ble_hci_trans_buf_free(g_ble_ll_sync_create_comp_ev); + g_ble_ll_sync_create_comp_ev = NULL; + } +} + +void +ble_ll_sync_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(g_ble_ll_sync_adv_list); i++) { + g_ble_ll_sync_adv_list[i].adv_sid = 0xff; + } +} +#endif +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_trace.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_trace.c new file mode 100644 index 000000000..c5d2b1d41 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_trace.c @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef ESP_PLATFORM +#include +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/os/os_trace_api.h" + +#if MYNEWT_VAL(BLE_LL_SYSVIEW) + +static os_trace_module_t g_ble_ll_trace_mod; +uint32_t ble_ll_trace_off; + +static void +ble_ll_trace_module_send_desc(void) +{ + os_trace_module_desc(&g_ble_ll_trace_mod, "0 ll_sched lls=%u cputime=%u start_time=%u"); + os_trace_module_desc(&g_ble_ll_trace_mod, "1 ll_rx_start lls=%u pdu_type=%x"); + os_trace_module_desc(&g_ble_ll_trace_mod, "2 ll_rx_end pdu_type=%x len=%u flags=%x"); + os_trace_module_desc(&g_ble_ll_trace_mod, "3 ll_wfr_timer_exp lls=%u xcvr=%u rx_start=%u"); + os_trace_module_desc(&g_ble_ll_trace_mod, "4 ll_ctrl_rx opcode=%u len=%u"); + os_trace_module_desc(&g_ble_ll_trace_mod, "5 ll_conn_ev_start conn_handle=%u"); + os_trace_module_desc(&g_ble_ll_trace_mod, "6 ll_conn_ev_end conn_handle=%u event_cntr=%u"); + os_trace_module_desc(&g_ble_ll_trace_mod, "7 ll_conn_end conn_handle=%u event_cntr=%u err=%u"); + os_trace_module_desc(&g_ble_ll_trace_mod, "8 ll_conn_tx len=%u offset=%u"); + os_trace_module_desc(&g_ble_ll_trace_mod, "9 ll_conn_rx conn_sn=%u pdu_nesn=%u"); + os_trace_module_desc(&g_ble_ll_trace_mod, "10 ll_adv_txdone inst=%u chanset=%x"); + os_trace_module_desc(&g_ble_ll_trace_mod, "11 ll_adv_halt inst=%u"); + os_trace_module_desc(&g_ble_ll_trace_mod, "12 ll_aux_ref aux=%p ref=%u"); + os_trace_module_desc(&g_ble_ll_trace_mod, "13 ll_aux_unref aux=%p ref=%u"); +} + +void +ble_ll_trace_init(void) +{ + ble_ll_trace_off = + os_trace_module_register(&g_ble_ll_trace_mod, "ble_ll", 12, + ble_ll_trace_module_send_desc); +} +#endif +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_utils.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_utils.c new file mode 100644 index 000000000..3814e58a8 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_utils.c @@ -0,0 +1,303 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef ESP_PLATFORM + +#include +#include +#include "nimble/nimble/include/nimble/ble.h" +#include "../include/controller/ble_ll.h" +#include "../include/controller/ble_ll_utils.h" + +/* 37 bits require 5 bytes */ +#define BLE_LL_CHMAP_LEN (5) + +/* Sleep clock accuracy table (in ppm) */ +static const uint16_t g_ble_sca_ppm_tbl[8] = { + 500, 250, 150, 100, 75, 50, 30, 20 +}; + +uint32_t +ble_ll_utils_calc_access_addr(void) +{ + uint32_t aa; + uint16_t aa_low; + uint16_t aa_high; + uint32_t temp; + uint32_t mask; + uint32_t prev_bit; + uint8_t bits_diff; + uint8_t consecutive; + uint8_t transitions; + uint8_t ones; + int tmp; + + /* Calculate a random access address */ + aa = 0; + while (1) { + /* Get two, 16-bit random numbers */ + aa_low = rand() & 0xFFFF; + aa_high = rand() & 0xFFFF; + + /* All four bytes cannot be equal */ + if (aa_low == aa_high) { + continue; + } + + /* Upper 6 bits must have 2 transitions */ + tmp = (int16_t)aa_high >> 10; + if (__builtin_popcount(tmp ^ (tmp >> 1)) < 2) { + continue; + } + + /* Cannot be access address or be 1 bit different */ + aa = aa_high; + aa = (aa << 16) | aa_low; + bits_diff = 0; + temp = aa ^ BLE_ACCESS_ADDR_ADV; + for (mask = 0x00000001; mask != 0; mask <<= 1) { + if (mask & temp) { + ++bits_diff; + if (bits_diff > 1) { + break; + } + } + } + if (bits_diff <= 1) { + continue; + } + + /* Cannot have more than 24 transitions */ + transitions = 0; + consecutive = 1; + ones = 0; + mask = 0x00000001; + while (mask < 0x80000000) { + prev_bit = aa & mask; + mask <<= 1; + if (mask & aa) { + if (prev_bit == 0) { + ++transitions; + consecutive = 1; + } else { + ++consecutive; + } + } else { + if (prev_bit == 0) { + ++consecutive; + } else { + ++transitions; + consecutive = 1; + } + } + + if (prev_bit) { + ones++; + } + + /* 8 lsb should have at least three 1 */ + if (mask == 0x00000100 && ones < 3) { + break; + } + + /* 16 lsb should have no more than 11 transitions */ + if (mask == 0x00010000 && transitions > 11) { + break; + } + + /* This is invalid! */ + if (consecutive > 6) { + /* Make sure we always detect invalid sequence below */ + mask = 0; + break; + } + } + + /* Invalid sequence found */ + if (mask != 0x80000000) { + continue; + } + + /* Cannot be more than 24 transitions */ + if (transitions > 24) { + continue; + } + + /* We have a valid access address */ + break; + } + return aa; +} + +uint8_t +ble_ll_utils_remapped_channel(uint8_t remap_index, const uint8_t *chanmap) +{ + uint8_t cntr; + uint8_t mask; + uint8_t usable_chans; + uint8_t chan; + int i, j; + + /* NOTE: possible to build a map but this would use memory. For now, + * we just calculate + * Iterate through channel map to find this channel + */ + chan = 0; + cntr = 0; + for (i = 0; i < BLE_LL_CHMAP_LEN; i++) { + usable_chans = chanmap[i]; + if (usable_chans != 0) { + mask = 0x01; + for (j = 0; j < 8; j++) { + if (usable_chans & mask) { + if (cntr == remap_index) { + return (chan + j); + } + ++cntr; + } + mask <<= 1; + } + } + chan += 8; + } + + /* we should never reach here */ + BLE_LL_ASSERT(0); + return 0; +} + +uint8_t +ble_ll_utils_calc_num_used_chans(const uint8_t *chmap) +{ + int i; + int j; + uint8_t mask; + uint8_t chanbyte; + uint8_t used_channels; + + used_channels = 0; + for (i = 0; i < BLE_LL_CHMAP_LEN; ++i) { + chanbyte = chmap[i]; + if (chanbyte) { + if (chanbyte == 0xff) { + used_channels += 8; + } else { + mask = 0x01; + for (j = 0; j < 8; ++j) { + if (chanbyte & mask) { + ++used_channels; + } + mask <<= 1; + } + } + } + } + return used_channels; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) +static uint16_t +ble_ll_utils_csa2_perm(uint16_t in) +{ + uint16_t out = 0; + int i; + + for (i = 0; i < 8; i++) { + out |= ((in >> i) & 0x00000001) << (7 - i); + } + + for (i = 8; i < 16; i++) { + out |= ((in >> i) & 0x00000001) << (15 + 8 - i); + } + + return out; +} + +static uint16_t +ble_ll_utils_csa2_prng(uint16_t counter, uint16_t ch_id) +{ + uint16_t prn_e; + + prn_e = counter ^ ch_id; + + prn_e = ble_ll_utils_csa2_perm(prn_e); + prn_e = (prn_e * 17) + ch_id; + + prn_e = ble_ll_utils_csa2_perm(prn_e); + prn_e = (prn_e * 17) + ch_id; + + prn_e = ble_ll_utils_csa2_perm(prn_e); + prn_e = (prn_e * 17) + ch_id; + + prn_e = prn_e ^ ch_id; + + return prn_e; +} + +uint8_t +ble_ll_utils_calc_dci_csa2(uint16_t event_cntr, uint16_t channel_id, + uint8_t num_used_chans, const uint8_t *chanmap) +{ + uint16_t channel_unmapped; + uint8_t remap_index; + + uint16_t prn_e; + uint8_t bitpos; + + prn_e = ble_ll_utils_csa2_prng(event_cntr, channel_id); + + channel_unmapped = prn_e % 37; + + /* + * If unmapped channel is the channel index of a used channel it is used + * as channel index. + */ + bitpos = 1 << (channel_unmapped & 0x07); + if (chanmap[channel_unmapped >> 3] & bitpos) { + return channel_unmapped; + } + + remap_index = (num_used_chans * prn_e) / 0x10000; + + return ble_ll_utils_remapped_channel(remap_index, chanmap); +} +#endif + +uint32_t +ble_ll_utils_calc_window_widening(uint32_t anchor_point, + uint32_t last_anchor_point, + uint8_t master_sca) +{ + uint32_t total_sca_ppm; + uint32_t window_widening; + int32_t time_since_last_anchor; + uint32_t delta_msec; + + window_widening = 0; + + time_since_last_anchor = (int32_t)(anchor_point - last_anchor_point); + if (time_since_last_anchor > 0) { + delta_msec = os_cputime_ticks_to_usecs(time_since_last_anchor) / 1000; + total_sca_ppm = g_ble_sca_ppm_tbl[master_sca] + + MYNEWT_VAL(BLE_LL_OUR_SCA); + window_widening = (total_sca_ppm * delta_msec) / 1000; + } + + return window_widening; +} +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_whitelist.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_whitelist.c new file mode 100644 index 000000000..8b9251117 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_whitelist.c @@ -0,0 +1,297 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef ESP_PLATFORM + +#include +#include +#include +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/include/nimble/nimble_opt.h" + +#if defined(ARDUINO_ARCH_NRF5) && defined(NRF51) +#include "nimble/nimble/drivers/nrf51/include/ble/xcvr.h" +#elif defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) +#include "nimble/nimble/drivers/nrf52/include/ble/xcvr.h" +#endif + +#include "../include/controller/ble_ll_whitelist.h" +#include "../include/controller/ble_ll_hci.h" +#include "../include/controller/ble_ll_adv.h" +#include "../include/controller/ble_ll_scan.h" +#include "../include/controller/ble_hw.h" + +#if (MYNEWT_VAL(BLE_LL_WHITELIST_SIZE) < BLE_HW_WHITE_LIST_SIZE) +#define BLE_LL_WHITELIST_SIZE MYNEWT_VAL(BLE_LL_WHITELIST_SIZE) +#else +#define BLE_LL_WHITELIST_SIZE BLE_HW_WHITE_LIST_SIZE +#endif + +struct ble_ll_whitelist_entry +{ + uint8_t wl_valid; + uint8_t wl_addr_type; + uint8_t wl_dev_addr[BLE_DEV_ADDR_LEN]; +}; + +struct ble_ll_whitelist_entry g_ble_ll_whitelist[BLE_LL_WHITELIST_SIZE]; + +static int +ble_ll_whitelist_chg_allowed(void) +{ + int rc; + + /* + * This command is not allowed if: + * -> advertising uses the whitelist and we are currently advertising. + * -> scanning uses the whitelist and is enabled. + * -> initiating uses whitelist and a LE create connection command is in + * progress + */ + rc = 1; + if (!ble_ll_adv_can_chg_whitelist() || !ble_ll_scan_can_chg_whitelist()) { + rc = 0; + } + return rc; +} + +/** + * Clear the whitelist. + * + * @return int 0: success, BLE error code otherwise + */ +int +ble_ll_whitelist_clear(void) +{ + int i; + struct ble_ll_whitelist_entry *wl; + + /* Check proper state */ + if (!ble_ll_whitelist_chg_allowed()) { + return BLE_ERR_CMD_DISALLOWED; + } + + /* Set the number of entries to 0 */ + wl = &g_ble_ll_whitelist[0]; + for (i = 0; i < BLE_LL_WHITELIST_SIZE; ++i) { + wl->wl_valid = 0; + ++wl; + } + +#if (BLE_USES_HW_WHITELIST == 1) + ble_hw_whitelist_clear(); +#endif + + return BLE_ERR_SUCCESS; +} + +/** + * Read the size of the whitelist. This is the total number of whitelist + * entries allowed by the controller. + * + * @param rspbuf Pointer to response buffer + * + * @return int 0: success. + */ +int +ble_ll_whitelist_read_size(uint8_t *rspbuf, uint8_t *rsplen) +{ + struct ble_hci_le_rd_white_list_rp *rsp = (void *) rspbuf; + + rsp->size = BLE_LL_WHITELIST_SIZE; + + *rsplen = sizeof(*rsp); + + return BLE_ERR_SUCCESS; +} + +/** + * Searches the whitelist to determine if the address is present in the + * whitelist. This is an internal API that only searches the link layer + * whitelist and does not care about the hardware whitelist + * + * @param addr Device or identity address to check. + * @param addr_type Public address (0) or random address (1) + * + * @return int 0: device is not on whitelist; otherwise the return value + * is the 'position' of the device in the whitelist (the index of the element + * plus 1). + */ +static int +ble_ll_whitelist_search(const uint8_t *addr, uint8_t addr_type) +{ + int i; + struct ble_ll_whitelist_entry *wl; + + wl = &g_ble_ll_whitelist[0]; + for (i = 0; i < BLE_LL_WHITELIST_SIZE; ++i) { + if ((wl->wl_valid) && (wl->wl_addr_type == addr_type) && + (!memcmp(&wl->wl_dev_addr[0], addr, BLE_DEV_ADDR_LEN))) { + return i + 1; + } + ++wl; + } + + return 0; +} + +/** + * Is there a match between the device and a device on the whitelist. + * + * NOTE: This API uses the HW, if present, to determine if there was a match + * between a received address and an address in the whitelist. If the HW does + * not support whitelisting this API is the same as the whitelist search API + * + * @param addr + * @param addr_type Public address (0) or random address (1) + * @param is_ident True if addr is an identity address; false otherwise + * + * @return int + */ +int +ble_ll_whitelist_match(uint8_t *addr, uint8_t addr_type, int is_ident) +{ + int rc; +#if (BLE_USES_HW_WHITELIST == 1) + /* + * XXX: This should be changed. This is HW specific: some HW may be able + * to both resolve a private address and perform a whitelist check. The + * current BLE hw cannot support this. + */ + if (is_ident) { + rc = ble_ll_whitelist_search(addr, addr_type); + } else { + rc = ble_hw_whitelist_match(); + } +#else + rc = ble_ll_whitelist_search(addr, addr_type); +#endif + return rc; +} + +/** + * Add a device to the whitelist + * + * @return int + */ +int +ble_ll_whitelist_add(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_add_whte_list_cp *cmd = (const void *) cmdbuf; + struct ble_ll_whitelist_entry *wl; + int rc; + int i; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Must be in proper state */ + if (!ble_ll_whitelist_chg_allowed()) { + return BLE_ERR_CMD_DISALLOWED; + } + + /* Check if we have any open entries */ + rc = BLE_ERR_SUCCESS; + if (!ble_ll_whitelist_search(cmd->addr, cmd->addr_type)) { + wl = &g_ble_ll_whitelist[0]; + for (i = 0; i < BLE_LL_WHITELIST_SIZE; ++i) { + if (wl->wl_valid == 0) { + memcpy(&wl->wl_dev_addr[0], cmd->addr, BLE_DEV_ADDR_LEN); + wl->wl_addr_type = cmd->addr_type; + wl->wl_valid = 1; + break; + } + ++wl; + } + + if (i == BLE_LL_WHITELIST_SIZE) { + rc = BLE_ERR_MEM_CAPACITY; + } else { +#if (BLE_USES_HW_WHITELIST == 1) + rc = ble_hw_whitelist_add(cmd->addr, cmd->addr_type); +#endif + } + } + + return rc; +} + +/** + * Remove a device from the whitelist + * + * @param cmdbuf + * + * @return int 0: success, BLE error code otherwise + */ +int +ble_ll_whitelist_rmv(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_rmv_white_list_cp *cmd = (const void *) cmdbuf; + int position; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Must be in proper state */ + if (!ble_ll_whitelist_chg_allowed()) { + return BLE_ERR_CMD_DISALLOWED; + } + + position = ble_ll_whitelist_search(cmd->addr, cmd->addr_type); + if (position) { + g_ble_ll_whitelist[position - 1].wl_valid = 0; + } + +#if (BLE_USES_HW_WHITELIST == 1) + ble_hw_whitelist_rmv(cmd->addr, cmd->addr_type); +#endif + + return BLE_ERR_SUCCESS; +} + +/** + * Enable whitelisting. + * + * Note: This function has no effect if we are not using HW whitelisting + */ +void +ble_ll_whitelist_enable(void) +{ +#if (BLE_USES_HW_WHITELIST == 1) + ble_hw_whitelist_enable(); +#endif +} + +/** + * Disable whitelisting. + * + * Note: This function has no effect if we are not using HW whitelisting + */ +void +ble_ll_whitelist_disable(void) +{ +#if (BLE_USES_HW_WHITELIST == 1) + ble_hw_whitelist_disable(); +#endif +} + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/syscfg.yml new file mode 100644 index 000000000..85049cb09 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/syscfg.yml @@ -0,0 +1,434 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +syscfg.defs: + BLE_CONTROLLER: + description: > + Indicates that NimBLE controller is present. The default value for + this setting shall not be overriden. + value: 1 + + BLE_HW_WHITELIST_ENABLE: + description: > + Used to enable hardware white list + value: 1 + + BLE_LL_SYSVIEW: + description: > + Enable SystemView tracing module for controller. + value: 0 + + BLE_LL_PRIO: + description: 'The priority of the LL task' + type: 'task_priority' + value: 0 + + # Sleep clock accuracy (sca). This is the amount of drift in the system + # during when the device is sleeping (in parts per million). + # + # NOTE: 'the' master sca is an enumerated value based on the sca. Rather + # than have a piece of code calculate this value, the developer must set + # this value based on the value of the SCA using the following table: + # + # SCA between 251 and 500 ppm (inclusive); master sca = 0 + # SCA between 151 and 250 ppm (inclusive); master sca = 1 + # SCA between 101 and 150 ppm (inclusive); master sca = 2 + # SCA between 76 and 100 ppm (inclusive); master sca = 3 + # SCA between 51 and 75 ppm (inclusive); master sca = 4 + # SCA between 31 and 50 ppm (inclusive); master sca = 5 + # SCA between 21 and 30 ppm (inclusive); master sca = 6 + # SCA between 0 and 20 ppm (inclusive); master sca = 7 + # + # For example: + # if your clock drift is 101 ppm, your master should be set to 2. + # if your clock drift is 20, your master sca should be set to 7. + # + # The values provided below are merely meant to be an example and should + # be replaced by values appropriate for your platform. + BLE_LL_OUR_SCA: + description: 'The system clock accuracy of the device.' + value: '60' # in ppm + + BLE_LL_MASTER_SCA: + description: 'Enumerated value based on our sca' + value: '4' + + BLE_LL_TX_PWR_DBM: + description: 'Transmit power level.' + value: '0' + + BLE_LL_NUM_COMP_PKT_ITVL_MS: + description: > + Determines the interval at which the controller will send the + number of completed packets event to the host. Rate is in milliseconds. + value: 2000 + + BLE_LL_MFRG_ID: + description: > + Manufacturer ID. Should be set to unique ID per manufacturer. + value: '0xFFFF' + + # Configuration items for the number of duplicate advertisers and the + # number of advertisers from which we have heard a scan response. + BLE_LL_NUM_SCAN_DUP_ADVS: + description: 'The number of duplicate advertisers stored.' + value: '8' + BLE_LL_NUM_SCAN_RSP_ADVS: + description: > + The number of advertisers from which we have heard a scan + response. Prevents sending duplicate events to host. + value: '8' + + BLE_LL_WHITELIST_SIZE: + description: 'Size of the LL whitelist.' + value: '8' + + BLE_LL_RESOLV_LIST_SIZE: + description: 'Size of the resolving list.' + value: '4' + + # Data length management definitions for connections. These define the + # maximum size of the PDU's that will be sent and/or received in a + # connection. + BLE_LL_MAX_PKT_SIZE: + description: 'The maximum PDU size that can be sent/received' + value: '251' + BLE_LL_SUPP_MAX_RX_BYTES: + description: 'The maximum supported received PDU size' + value: MYNEWT_VAL(BLE_LL_MAX_PKT_SIZE) + BLE_LL_SUPP_MAX_TX_BYTES: + description: 'The maximum supported transmit PDU size' + value: MYNEWT_VAL(BLE_LL_MAX_PKT_SIZE) + BLE_LL_CONN_INIT_MAX_TX_BYTES: + description: > + Used to set the initial maximum transmit PDU size in a + connection. If this is set to a value greater than 27, + the controller will automatically attempt to do the + data length update procedure. The host can always tell + the controller to update this value. + value: '27' + + # The number of slots that will be allocated to each connection + BLE_LL_CONN_INIT_SLOTS: + description: > + This is the number of "slots" allocated to a connection when scheduling + connections. Each slot is 1.25 msecs long. Note that a connection event may + last longer than the number of slots allocated here and may also end earlier + (depending on when the next scheduled event occurs and how much data needs + to be transferred in the connection). However, you will be guaranteed that + a connection event will be given this much time, if needed. Consecutively + scheduled items will be at least this far apart + value: '4' + + BLE_LL_CONN_INIT_MIN_WIN_OFFSET: + description: > + This is the minimum number of "slots" for WindowOffset value used for + CONNECT_IND when creating new connection as a master. Each slot is 1.25 + msecs long. Increasing this value will delay first connection event after + connection is created. However, older TI CC254x controllers cannot change + connection parameters later if WindowOffset was set to 0 in CONNECT_IND. To + ensure interoperability with such devices set this value to 2 (or more). + value: '0' + + # Strict scheduling + BLE_LL_STRICT_CONN_SCHEDULING: + description: > + Forces the scheduler on a central to schedule connections in fixed + time intervals called periods. If set to 0, the scheduler is not forced + to do this. If set to 1, the scheduler will only schedule connections at + period boundaries. See comments in ble_ll_sched.h for more details. + value: '0' + + BLE_LL_ADD_STRICT_SCHED_PERIODS: + description: > + The number of additional periods that will be allocated for strict + scheduling. The total # of periods allocated for strict scheduling + will be equal to the number of connections plus this number. + value: '0' + + BLE_LL_USECS_PER_PERIOD: + description: > + The number of usecs per period. + value: '3250' + + # The number of random bytes to store + BLE_LL_RNG_BUFSIZE: + description: > + The number of random bytes that the link layer will try to + always have available for the host to use. Decreasing this + value may cause host delays if the host needs lots of random + material often. + value: '32' + + BLE_LL_RFMGMT_ENABLE_TIME: + description: > + Time required for radio and/or related components to be fully + enabled before any request from LL is sent. This value is used + by rfmgmt to enable PHY in advance, before request from LL is + made. It depends on radio driver selected and may also depend + on hardware used: + - nrf51 - time required for XTAL to settle + - nrf52 - time required for XTAL to settle + Value is specified in microseconds. If set to 0, rfmgmt keeps + PHY enabled all the time. + value: MYNEWT_VAL(BLE_XTAL_SETTLE_TIME) + + # Configuration for LL supported features. + # + # There are a total 8 features that the LL can support. These can be found + # in v4.2, Vol 6 Part B Section 4.6. + # + # These feature definitions are used to inform a host or other controller + # about the LL features supported by the controller. + # + # NOTE: 'the' controller always supports extended reject indicate and thus + # is not listed here. + + + BLE_LL_CFG_FEAT_LE_ENCRYPTION: + description: > + This option enables/disables encryption support in the controller. + This option saves both both code and RAM. + value: '1' + + BLE_LL_CFG_FEAT_CONN_PARAM_REQ: + description: > + This option enables/disables the connection parameter request + procedure. This is implemented in the controller but is disabled + by default. + value: '1' + + BLE_LL_CFG_FEAT_SLAVE_INIT_FEAT_XCHG: + description: > + This option allows a slave to initiate the feature exchange + procedure. This feature is implemented but currently has no impact + on code or ram size + value: '1' + + BLE_LL_CFG_FEAT_LE_PING: + description: > + This option allows a controller to send/receive LE pings. + Currently, this feature is not implemented by the controller so + turning it on or off has no effect. + value: 'MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_ENCRYPTION' + + BLE_LL_CFG_FEAT_DATA_LEN_EXT: + description: > + This option enables/disables the data length update procedure in + the controller. If enabled, the controller is allowed to change the + size of tx/rx pdu's used in a connection. This option has only + minor impact on code size and non on RAM. + value: '1' + + BLE_LL_CFG_FEAT_LL_PRIVACY: + description: > + This option is used to enable/disable LL privacy. + value: '1' + + BLE_LL_CFG_FEAT_LE_CSA2: + description: > + This option is used to enable/disable support for LE Channel + Selection Algorithm #2. + value: '0' + + BLE_LL_CFG_FEAT_LE_2M_PHY: + description: > + This option is used to enable/disable support for the 2Mbps PHY. + value: '0' + + BLE_LL_CFG_FEAT_LE_CODED_PHY: + description: > + This option is used to enable/disable support for the coded PHY. + value: '0' + + BLE_LL_CFG_FEAT_LL_EXT_ADV: + description: > + This option is used to enable/disable support for Extended + Advertising Feature. That means extended scanner, advertiser + and connect. + value: MYNEWT_VAL(BLE_EXT_ADV) + + BLE_LL_CFG_FEAT_LL_PERIODIC_ADV: + description: > + This option is used to enable/disable support for Periodic + Advertising Feature. + value: MYNEWT_VAL(BLE_PERIODIC_ADV) + + BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_CNT: + description: > + This option is used to configure number of supported periodic syncs. + value: MYNEWT_VAL(BLE_MAX_PERIODIC_SYNCS) + + BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_LIST_CNT: + description: > + Size of Periodic Advertiser sync list. + value: MYNEWT_VAL(BLE_MAX_PERIODIC_SYNCS) + + BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER: + description: > + This option is use to enable/disable support for Periodic + Advertising Sync Transfer Feature. + value: MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER) + + BLE_LL_EXT_ADV_AUX_PTR_CNT: + description: > + This option configure a max number of scheduled outstanding auxiliary + packets for receive on secondary advertising channel. + value: 0 + + BLE_PUBLIC_DEV_ADDR: + description: > + Allows the target or app to override the public device address + used by the controller. If all zero, the controller will + attempt to retrieve the public device address from its + chip specific location. If non-zero, this address will + be used. + value: "(uint8_t[6]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00}" + + BLE_LL_DTM: + description: > + Enables HCI Test commands needed for Bluetooth SIG certification + value: MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) + BLE_LL_DTM_EXTENSIONS: + description: > + Enables non-standard extensions to HCI test commands. Once enabled, + HCI_LE_Transmitter_Test accepts extra parameters in addition to + those defined in Core specification + interval (2 octets) interval between packets (usecs), overrides + standard interval + pkt_count (2 octets) number of packets to transmit, controller + will automatically stop sending packets + after given number of packets was sent + Setting either of these parameters to 0 will configure for default + behavior, as per Core specification. + If specified interval is shorter then allowed by specification it + will be ignored. + Extended parameters shall immediately follow standard parameters. + Controller can accept both standard and extended version of command + depending on specified HCI command length. + value: 0 + + BLE_LL_VND_EVENT_ON_ASSERT: + description: > + This options enables controller to send a vendor-specific event on + an assertion in controller code. The event contains file name and + line number where assertion occured. + value: 0 + + BLE_LL_SYSINIT_STAGE: + description: > + Sysinit stage for the NimBLE controller. + value: 250 + + BLE_LL_DEBUG_GPIO_HCI_CMD: + description: > + GPIO pin number to debug HCI commands flow. Pin is set to high state + when HCI command is being processed. + value: -1 + BLE_LL_DEBUG_GPIO_HCI_EV: + description: > + GPIO pin number to debug HCI events flow. Pin is set to high state + when HCI event is being sent. + value: -1 + BLE_LL_DEBUG_GPIO_SCHED_RUN: + description: > + GPIO pin number to debug scheduler running (on timer). Pin is set + to high state while scheduler is running. + value: -1 + BLE_LL_DEBUG_GPIO_SCHED_ITEM_CB: + description: > + GPIO pin number to debug scheduler item execution times. Pin is set + to high state while item is executed. + value: -1 + +# Below settings allow to change scheduler timings. These should be left at +# default values unless you know what you are doing! + BLE_LL_SCHED_AUX_MAFS_DELAY: + description: > + Additional delay [us] between last ADV_EXT_IND and AUX_ADV_IND PDUs + when scheduling extended advertising event. This extends T_MAFS. + value: 0 + BLE_LL_SCHED_AUX_CHAIN_MAFS_DELAY: + description: > + Additional delay [us] between consecutive AUX_CHAIN_IND PDUs + when scheduling extended or periodic advertising event. This extends + T_MAFS. + value: 0 + BLE_LL_SCHED_SCAN_AUX_PDU_LEN: + description: > + This is expected PDU len for AUX_ADV_IND and subsequent + AUX_CHAIN_IND. When scheduling scan scheduler will reserve time for + receiving this amount of time. Setting this to high value improves + reception of large PDUs but results in wasting scheduler space when + receiving small PDUs only. On the other hand too low value can + result in not being able to scan whole PDU due to being preempted + by next scheduled item. By default size matching legacy ADV_IND PDU + payload is used: ExtHeader (Flags, AdvA, ADI) + 31 bytes of data. + range: 1..257 + value: 41 + + BLE_LL_SCHED_SCAN_SYNC_PDU_LEN: + description: > + This is expected PDU len for AUX_SYNC_IND and subsequent + AUX_CHAIN_IND. When scheduling scan scheduler will reserve time for + receiving this amount of time. Setting this to high value improves + reception of large PDUs but results in wasting scheduler space when + receiving small PDUs only. On the other hand too low value can + result in not being able to scan whole PDU due to being preempted + by next scheduled item. By default size matching PDU with legacy + data size is used: ExtHeader + 31 bytes of data. + range: 1..257 + value: 32 + +# deprecated settings (to be defunct/removed eventually) + BLE_LL_DIRECT_TEST_MODE: + description: use BLE_LL_DTM instead + value: 0 + deprecated: 1 + BLE_XTAL_SETTLE_TIME: + description: use BLE_LL_RFMGMT_ENABLE_TIME instead + value: 0 + deprecated: 1 + +# defunct settings (to be removed eventually) + BLE_DEVICE: + description: Superseded by BLE_CONTROLLER + value: 1 + defunct: 1 + BLE_LP_CLOCK: + description: Superseded by BLE_CONTROLLER + value: 1 + defunct: 1 + BLE_NUM_COMP_PKT_RATE: + description: Superseded by BLE_LL_NUM_COMP_PKT_ITVL_MS + value: '(2 * OS_TICKS_PER_SEC)' + defunct: 1 + + +syscfg.vals.BLE_LL_CFG_FEAT_LL_EXT_ADV: + BLE_LL_CFG_FEAT_LE_CSA2: 1 + BLE_HW_WHITELIST_ENABLE: 0 + BLE_LL_EXT_ADV_AUX_PTR_CNT: 5 + +# Enable vendor event on assert in standalone build to make failed assertions in +# controller code visible when connected to external host +syscfg.vals.!BLE_HOST: + BLE_LL_VND_EVENT_ON_ASSERT: 1 + +syscfg.restrictions: + - OS_CPUTIME_FREQ == 32768 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/include/ble/xcvr.h similarity index 55% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/include/ble/xcvr.h index 86157da0f..6c1fb7b24 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/include/ble/xcvr.h @@ -17,30 +17,35 @@ * under the License. */ -#ifndef H_BLE_HS_PVCY_PRIV_ -#define H_BLE_HS_PVCY_PRIV_ + #if defined(ARDUINO_ARCH_NRF5) && defined(NRF51) -#include +#ifndef H_BLE_XCVR_ +#define H_BLE_XCVR_ #ifdef __cplusplus extern "C" { #endif -extern const uint8_t ble_hs_pvcy_default_irk[16]; +/* Transceiver specific defintions */ +/* NOTE: we have to account for the RTC output compare issue */ +#define XCVR_PROC_DELAY_USECS (230) -int ble_hs_pvcy_set_our_irk(const uint8_t *irk); -int ble_hs_pvcy_our_irk(const uint8_t **out_irk); -int ble_hs_pvcy_remove_entry(uint8_t addr_type, const uint8_t *addr); -int ble_hs_pvcy_add_entry(const uint8_t *addr, uint8_t addrtype, - const uint8_t *irk); -int ble_hs_pvcy_ensure_started(void); -int ble_hs_pvcy_set_mode(const ble_addr_t *addr, uint8_t priv_mode); -#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY) -bool ble_hs_pvcy_enabled(void); -#endif +#define XCVR_RX_START_DELAY_USECS (140) +#define XCVR_TX_START_DELAY_USECS (140) +#define XCVR_TX_SCHED_DELAY_USECS \ + (XCVR_TX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS) +#define XCVR_RX_SCHED_DELAY_USECS \ + (XCVR_RX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS) + +/* + * Define HW whitelist size. This is the total possible whitelist size; + * not necessarily the size that will be used (may be smaller) + */ +#define BLE_HW_WHITE_LIST_SIZE (8) #ifdef __cplusplus } #endif +#endif /* H_BLE_XCVR_ */ #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/pkg.yml new file mode 100644 index 000000000..816a56355 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/pkg.yml @@ -0,0 +1,31 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: nimble/drivers/nrf51 +pkg.description: BLE driver for nRF51 systems. +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - ble + - bluetooth + +pkg.apis: ble_driver +pkg.deps: + - nimble + - nimble/controller diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/src/ble_hw.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/src/ble_hw.c new file mode 100644 index 000000000..3d4966b2d --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/src/ble_hw.c @@ -0,0 +1,491 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#if defined(ARDUINO_ARCH_NRF5) && defined(NRF51) + +#include +#include +#include +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "../include/ble/xcvr.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/include/nimble/nimble_opt.h" +#include "nrf.h" +#include "nimble/nimble/controller/include/controller/ble_hw.h" +#if MYNEWT +#include "mcu/cmsis_nvic.h" +#else +#include "core_cm0.h" +#include "nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h" +#endif +#include "nimble/porting/nimble/include/os/os_trace_api.h" + +/* Total number of resolving list elements */ +#define BLE_HW_RESOLV_LIST_SIZE (16) + +/* We use this to keep track of which entries are set to valid addresses */ +static uint8_t g_ble_hw_whitelist_mask; + +/* Random number generator isr callback */ +ble_rng_isr_cb_t g_ble_rng_isr_cb; + +/* If LL privacy is enabled, allocate memory for AAR */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + +/* The NRF51 supports up to 16 IRK entries */ +#if (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE) < 16) +#define NRF_IRK_LIST_ENTRIES (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE)) +#else +#define NRF_IRK_LIST_ENTRIES (16) +#endif + +/* NOTE: each entry is 16 bytes long. */ +uint32_t g_nrf_irk_list[NRF_IRK_LIST_ENTRIES * 4]; + +/* Current number of IRK entries */ +uint8_t g_nrf_num_irks; + +#endif + +/* Returns public device address or -1 if not present */ +int +ble_hw_get_public_addr(ble_addr_t *addr) +{ + uint32_t addr_high; + uint32_t addr_low; + + /* Does FICR have a public address */ + if ((NRF_FICR->DEVICEADDRTYPE & 1) != 0) { + return -1; + } + + /* Copy into device address. We can do this because we know platform */ + addr_low = NRF_FICR->DEVICEADDR[0]; + addr_high = NRF_FICR->DEVICEADDR[1]; + memcpy(addr->val, &addr_low, 4); + memcpy(&addr->val[4], &addr_high, 2); + addr->type = BLE_ADDR_PUBLIC; + + return 0; +} + +/* Returns random static address or -1 if not present */ +int +ble_hw_get_static_addr(ble_addr_t *addr) +{ + int rc; + + if ((NRF_FICR->DEVICEADDRTYPE & 1) == 1) { + memcpy(addr->val, (void *)&NRF_FICR->DEVICEADDR[0], 4); + memcpy(&addr->val[4], (void *)&NRF_FICR->DEVICEADDR[1], 2); + addr->val[5] |= 0xc0; + addr->type = BLE_ADDR_RANDOM; + rc = 0; + } else { + rc = -1; + } + + return rc; +} + +/** + * Clear the whitelist + * + * @return int + */ +void +ble_hw_whitelist_clear(void) +{ + NRF_RADIO->DACNF = 0; + g_ble_hw_whitelist_mask = 0; +} + +/** + * Add a device to the hw whitelist + * + * @param addr + * @param addr_type + * + * @return int 0: success, BLE error code otherwise + */ +int +ble_hw_whitelist_add(const uint8_t *addr, uint8_t addr_type) +{ + int i; + uint32_t mask; + + /* Find first ununsed device address match element */ + mask = 0x01; + for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) { + if ((mask & g_ble_hw_whitelist_mask) == 0) { + NRF_RADIO->DAB[i] = get_le32(addr); + NRF_RADIO->DAP[i] = get_le16(addr + 4); + if (addr_type == BLE_ADDR_RANDOM) { + NRF_RADIO->DACNF |= (mask << 8); + } + g_ble_hw_whitelist_mask |= mask; + return BLE_ERR_SUCCESS; + } + mask <<= 1; + } + + return BLE_ERR_MEM_CAPACITY; +} + +/** + * Remove a device from the hw whitelist + * + * @param addr + * @param addr_type + * + */ +void +ble_hw_whitelist_rmv(const uint8_t *addr, uint8_t addr_type) +{ + int i; + uint8_t cfg_addr; + uint16_t dap; + uint16_t txadd; + uint32_t dab; + uint32_t mask; + + /* Find first ununsed device address match element */ + dab = get_le32(addr); + dap = get_le16(addr + 4); + txadd = NRF_RADIO->DACNF >> 8; + mask = 0x01; + for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) { + if (mask & g_ble_hw_whitelist_mask) { + if ((dab == NRF_RADIO->DAB[i]) && (dap == NRF_RADIO->DAP[i])) { + cfg_addr = txadd & mask; + if (addr_type == BLE_ADDR_RANDOM) { + if (cfg_addr != 0) { + break; + } + } else { + if (cfg_addr == 0) { + break; + } + } + } + } + mask <<= 1; + } + + if (i < BLE_HW_WHITE_LIST_SIZE) { + g_ble_hw_whitelist_mask &= ~mask; + NRF_RADIO->DACNF &= ~mask; + } +} + +/** + * Returns the size of the whitelist in HW + * + * @return int Number of devices allowed in whitelist + */ +uint8_t +ble_hw_whitelist_size(void) +{ + return BLE_HW_WHITE_LIST_SIZE; +} + +/** + * Enable the whitelisted devices + */ +void +ble_hw_whitelist_enable(void) +{ + /* Enable the configured device addresses */ + NRF_RADIO->DACNF |= g_ble_hw_whitelist_mask; +} + +/** + * Disables the whitelisted devices + */ +void +ble_hw_whitelist_disable(void) +{ + /* Disable all whitelist devices */ + NRF_RADIO->DACNF &= 0x0000ff00; +} + +/** + * Boolean function which returns true ('1') if there is a match on the + * whitelist. + * + * @return int + */ +int +ble_hw_whitelist_match(void) +{ + return (int)NRF_RADIO->EVENTS_DEVMATCH; +} + +/* Encrypt data */ +int +ble_hw_encrypt_block(struct ble_encryption_block *ecb) +{ + int rc; + uint32_t end; + uint32_t err; + + /* Stop ECB */ + NRF_ECB->TASKS_STOPECB = 1; + /* XXX: does task stop clear these counters? Anyway to do this quicker? */ + NRF_ECB->EVENTS_ENDECB = 0; + NRF_ECB->EVENTS_ERRORECB = 0; + NRF_ECB->ECBDATAPTR = (uint32_t)ecb; + + /* Start ECB */ + NRF_ECB->TASKS_STARTECB = 1; + + /* Wait till error or done */ + rc = 0; + while (1) { + end = NRF_ECB->EVENTS_ENDECB; + err = NRF_ECB->EVENTS_ERRORECB; + if (end || err) { + if (err) { + rc = -1; + } + break; + } + } + + return rc; +} + +/** + * Random number generator ISR. + */ +static void +ble_rng_isr(void) +{ + uint8_t rnum; + + os_trace_isr_enter(); + + /* No callback? Clear and disable interrupts */ + if (g_ble_rng_isr_cb == NULL) { + NRF_RNG->INTENCLR = 1; + NRF_RNG->EVENTS_VALRDY = 0; + (void)NRF_RNG->SHORTS; + os_trace_isr_exit(); + return; + } + + /* If there is a value ready grab it */ + if (NRF_RNG->EVENTS_VALRDY) { + NRF_RNG->EVENTS_VALRDY = 0; + rnum = (uint8_t)NRF_RNG->VALUE; + (*g_ble_rng_isr_cb)(rnum); + } + + os_trace_isr_exit(); +} + +/** + * Initialize the random number generator + * + * @param cb + * @param bias + * + * @return int + */ +int +ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias) +{ + /* Set bias */ + if (bias) { + NRF_RNG->CONFIG = 1; + } else { + NRF_RNG->CONFIG = 0; + } + + /* If we were passed a function pointer we need to enable the interrupt */ + if (cb != NULL) { +#ifndef RIOT_VERSION + NVIC_SetPriority(RNG_IRQn, (1 << __NVIC_PRIO_BITS) - 1); +#endif +#if MYNEWT + NVIC_SetVector(RNG_IRQn, (uint32_t)ble_rng_isr); +#else + ble_npl_hw_set_isr(RNG_IRQn, ble_rng_isr); +#endif + NVIC_EnableIRQ(RNG_IRQn); + g_ble_rng_isr_cb = cb; + } + + return 0; +} + +/** + * Start the random number generator + * + * @return int + */ +int +ble_hw_rng_start(void) +{ + os_sr_t sr; + + /* No need for interrupt if there is no callback */ + OS_ENTER_CRITICAL(sr); + NRF_RNG->EVENTS_VALRDY = 0; + if (g_ble_rng_isr_cb) { + NRF_RNG->INTENSET = 1; + } + NRF_RNG->TASKS_START = 1; + OS_EXIT_CRITICAL(sr); + + return 0; +} + +/** + * Stop the random generator + * + * @return int + */ +int +ble_hw_rng_stop(void) +{ + os_sr_t sr; + + /* No need for interrupt if there is no callback */ + OS_ENTER_CRITICAL(sr); + NRF_RNG->INTENCLR = 1; + NRF_RNG->TASKS_STOP = 1; + NRF_RNG->EVENTS_VALRDY = 0; + OS_EXIT_CRITICAL(sr); + + return 0; +} + +/** + * Read the random number generator. + * + * @return uint8_t + */ +uint8_t +ble_hw_rng_read(void) +{ + uint8_t rnum; + + /* Wait for a sample */ + while (NRF_RNG->EVENTS_VALRDY == 0) { + } + + NRF_RNG->EVENTS_VALRDY = 0; + rnum = (uint8_t)NRF_RNG->VALUE; + + return rnum; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) +/** + * Clear the resolving list + * + * @return int + */ +void +ble_hw_resolv_list_clear(void) +{ + g_nrf_num_irks = 0; +} + +/** + * Add a device to the hw resolving list + * + * @param irk Pointer to IRK to add + * + * @return int 0: success, BLE error code otherwise + */ +int +ble_hw_resolv_list_add(uint8_t *irk) +{ + uint32_t *nrf_entry; + + /* Find first ununsed device address match element */ + if (g_nrf_num_irks == NRF_IRK_LIST_ENTRIES) { + return BLE_ERR_MEM_CAPACITY; + } + + /* Copy into irk list */ + nrf_entry = &g_nrf_irk_list[4 * g_nrf_num_irks]; + memcpy(nrf_entry, irk, 16); + + /* Add to total */ + ++g_nrf_num_irks; + return BLE_ERR_SUCCESS; +} + +/** + * Remove a device from the hw resolving list + * + * @param index Index of IRK to remove + */ +void +ble_hw_resolv_list_rmv(int index) +{ + uint32_t *irk_entry; + + if (index < g_nrf_num_irks) { + --g_nrf_num_irks; + irk_entry = &g_nrf_irk_list[index]; + if (g_nrf_num_irks > index) { + memmove(irk_entry, irk_entry + 4, 16 * (g_nrf_num_irks - index)); + } + } +} + +/** + * Returns the size of the resolving list. NOTE: this returns the maximum + * allowable entries in the HW. Configuration options may limit this. + * + * @return int Number of devices allowed in resolving list + */ +uint8_t +ble_hw_resolv_list_size(void) +{ + return BLE_HW_RESOLV_LIST_SIZE; +} + +/** + * Called to determine if the address received was resolved. + * + * @return int Negative values indicate unresolved address; positive values + * indicate index in resolving list of resolved address. + */ +int +ble_hw_resolv_list_match(void) +{ + uint32_t index; + + if (NRF_AAR->EVENTS_END) { + if (NRF_AAR->EVENTS_RESOLVED) { + index = NRF_AAR->STATUS; + return (int)index; + } + } + + return -1; +} +#endif +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/src/ble_phy.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/src/ble_phy.c new file mode 100644 index 000000000..3bfed096a --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/src/ble_phy.c @@ -0,0 +1,1527 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + #if defined(ARDUINO_ARCH_NRF5) && defined(NRF51) + +#include +#include +#include +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "../include/ble/xcvr.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/include/nimble/nimble_opt.h" +#include "nimble/nimble/controller/include/controller/ble_phy.h" +#include "nimble/nimble/controller/include/controller/ble_phy_trace.h" +#include "nimble/nimble/controller/include/controller/ble_ll.h" +#include "nrf.h" + +#if MYNEWT +#include "mcu/nrf51_clock.h" +#include "mcu/cmsis_nvic.h" +#else +#include "core_cm0.h" +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) +#error LE 2M PHY cannot be enabled on nRF51 +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) +#error LE Coded PHY cannot be enabled on nRF51 +#endif + +/* XXX: 4) Make sure RF is higher priority interrupt than schedule */ + +/* + * XXX: Maximum possible transmit time is 1 msec for a 60ppm crystal + * and 16ms for a 30ppm crystal! We need to limit PDU size based on + * crystal accuracy. Look at this in the spec. + */ + +/* XXX: private header file? */ +extern uint8_t g_nrf_num_irks; +extern uint32_t g_nrf_irk_list[]; + +/* To disable all radio interrupts */ +#define NRF_RADIO_IRQ_MASK_ALL (0x34FF) + +/* + * We configure the nrf with a 1 byte S0 field, 8 bit length field, and + * zero bit S1 field. The preamble is 8 bits long. + */ +#define NRF_LFLEN_BITS (8) +#define NRF_S0_LEN (1) + +/* Maximum length of frames */ +#define NRF_MAXLEN (255) +#define NRF_BALEN (3) /* For base address of 3 bytes */ + +/* Maximum tx power */ +#define NRF_TX_PWR_MAX_DBM (4) +#define NRF_TX_PWR_MIN_DBM (-40) + +/* Max. encrypted payload length */ +#define NRF_MAX_ENCRYPTED_PYLD_LEN (27) +#define NRF_ENC_HDR_SIZE (3) +#define NRF_ENC_BUF_SIZE \ + (NRF_MAX_ENCRYPTED_PYLD_LEN + NRF_ENC_HDR_SIZE + BLE_LL_DATA_MIC_LEN) + +/* BLE PHY data structure */ +struct ble_phy_obj +{ + uint8_t phy_stats_initialized; + int8_t phy_txpwr_dbm; + uint8_t phy_chan; + uint8_t phy_state; + uint8_t phy_transition; + uint8_t phy_rx_started; + uint8_t phy_encrypted; + uint8_t phy_privacy; + uint8_t phy_tx_pyld_len; + uint8_t *rxdptr; + int8_t rx_pwr_compensation; + uint32_t phy_aar_scratch; + uint32_t phy_access_address; + struct ble_mbuf_hdr rxhdr; + void *txend_arg; + ble_phy_tx_end_func txend_cb; + uint32_t phy_start_cputime; +}; +struct ble_phy_obj g_ble_phy_data; + +/* XXX: if 27 byte packets desired we can make this smaller */ +/* Global transmit/receive buffer */ +static uint32_t g_ble_phy_tx_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; +static uint32_t g_ble_phy_rx_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) +/* Make sure word-aligned for faster copies */ +static uint32_t g_ble_phy_enc_buf[(NRF_ENC_BUF_SIZE + 3) / 4]; +#endif + +/* RF center frequency for each channel index (offset from 2400 MHz) */ +static const uint8_t g_ble_phy_chan_freq[BLE_PHY_NUM_CHANS] = { + 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, /* 0-9 */ + 24, 28, 30, 32, 34, 36, 38, 40, 42, 44, /* 10-19 */ + 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, /* 20-29 */ + 66, 68, 70, 72, 74, 76, 78, 2, 26, 80, /* 30-39 */ +}; + +/* Statistics */ +STATS_SECT_START(ble_phy_stats) + STATS_SECT_ENTRY(phy_isrs) + STATS_SECT_ENTRY(tx_good) + STATS_SECT_ENTRY(tx_fail) + STATS_SECT_ENTRY(tx_late) + STATS_SECT_ENTRY(tx_bytes) + STATS_SECT_ENTRY(rx_starts) + STATS_SECT_ENTRY(rx_aborts) + STATS_SECT_ENTRY(rx_valid) + STATS_SECT_ENTRY(rx_crc_err) + STATS_SECT_ENTRY(rx_late) + STATS_SECT_ENTRY(radio_state_errs) + STATS_SECT_ENTRY(rx_hw_err) + STATS_SECT_ENTRY(tx_hw_err) +STATS_SECT_END +STATS_SECT_DECL(ble_phy_stats) ble_phy_stats; + +STATS_NAME_START(ble_phy_stats) + STATS_NAME(ble_phy_stats, phy_isrs) + STATS_NAME(ble_phy_stats, tx_good) + STATS_NAME(ble_phy_stats, tx_fail) + STATS_NAME(ble_phy_stats, tx_late) + STATS_NAME(ble_phy_stats, tx_bytes) + STATS_NAME(ble_phy_stats, rx_starts) + STATS_NAME(ble_phy_stats, rx_aborts) + STATS_NAME(ble_phy_stats, rx_valid) + STATS_NAME(ble_phy_stats, rx_crc_err) + STATS_NAME(ble_phy_stats, rx_late) + STATS_NAME(ble_phy_stats, radio_state_errs) + STATS_NAME(ble_phy_stats, rx_hw_err) + STATS_NAME(ble_phy_stats, tx_hw_err) +STATS_NAME_END(ble_phy_stats) + +/* + * NOTE: + * Tested the following to see what would happen: + * -> NVIC has radio irq enabled (interrupt # 1, mask 0x2). + * -> Set up nrf to receive. Clear ADDRESS event register. + * -> Enable ADDRESS interrupt on nrf5 by writing to INTENSET. + * -> Enable RX. + * -> Disable interrupts globally using OS_ENTER_CRITICAL(). + * -> Wait until a packet is received and the ADDRESS event occurs. + * -> Call ble_phy_disable(). + * + * At this point I wanted to see the state of the cortex NVIC. The IRQ + * pending bit was TRUE for the radio interrupt (as expected) as we never + * serviced the radio interrupt (interrupts were disabled). + * + * What was unexpected was this: without clearing the pending IRQ in the NVIC, + * when radio interrupts were re-enabled (address event bit in INTENSET set to + * 1) and the radio ADDRESS event register read 1 (it was never cleared after + * the first address event), the radio did not enter the ISR! I would have + * expected that if the following were true, an interrupt would occur: + * -> NVIC ISER bit set to TRUE + * -> NVIC ISPR bit reads TRUE, meaning interrupt is pending. + * -> Radio peripheral interrupts are enabled for some event (or events). + * -> Corresponding event register(s) in radio peripheral read 1. + * + * Not sure what the end result of all this is. We will clear the pending + * bit in the NVIC just to be sure when we disable the PHY. + */ + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) +/* Per nordic, the number of bytes needed for scratch is 16 + MAX_PKT_SIZE. */ +#define NRF_ENC_SCRATCH_WORDS (((NRF_MAX_ENCRYPTED_PYLD_LEN + 16) + 3) / 4) + +uint32_t g_nrf_encrypt_scratchpad[NRF_ENC_SCRATCH_WORDS]; + +struct nrf_ccm_data +{ + uint8_t key[16]; + uint64_t pkt_counter; + uint8_t dir_bit; + uint8_t iv[8]; +} __attribute__((packed)); + +struct nrf_ccm_data g_nrf_ccm_data; +#endif + +/** + * Copies the data from the phy receive buffer into a mbuf chain. + * + * @param dptr Pointer to receive buffer + * @param rxpdu Pointer to already allocated mbuf chain + * + * NOTE: the packet header already has the total mbuf length in it. The + * lengths of the individual mbufs are not set prior to calling. + * + */ +void +ble_phy_rxpdu_copy(uint8_t *dptr, struct os_mbuf *rxpdu) +{ + uint32_t rem_len; + uint32_t copy_len; + uint32_t block_len; + uint32_t block_rem_len; + void *dst; + void *src; + struct os_mbuf * om; + + /* Better be aligned */ + assert(((uint32_t)dptr & 3) == 0); + + block_len = rxpdu->om_omp->omp_databuf_len; + rem_len = OS_MBUF_PKTHDR(rxpdu)->omp_len; + src = dptr; + + /* + * Setup for copying from first mbuf which is shorter due to packet header + * and extra leading space + */ + copy_len = block_len - rxpdu->om_pkthdr_len - 4; + om = rxpdu; + dst = om->om_data; + + while (true) { + /* + * Always copy blocks of length aligned to word size, only last mbuf + * will have remaining non-word size bytes appended. + */ + block_rem_len = copy_len; + copy_len = min(copy_len, rem_len); + copy_len &= ~3; + + dst = om->om_data; + om->om_len = copy_len; + rem_len -= copy_len; + block_rem_len -= copy_len; + + __asm__ volatile (".syntax unified \n" + " mov r4, %[len] \n" + " b 2f \n" + "1: ldr r3, [%[src], %[len]] \n" + " str r3, [%[dst], %[len]] \n" + "2: subs %[len], #4 \n" + " bpl 1b \n" + " adds %[src], %[src], r4 \n" + " adds %[dst], %[dst], r4 \n" + : [dst] "+l" (dst), [src] "+l" (src), + [len] "+l" (copy_len) + : + : "r3", "r4", "memory" + ); + + if ((rem_len < 4) && (block_rem_len >= rem_len)) { + break; + } + + /* Move to next mbuf */ + om = SLIST_NEXT(om, om_next); + copy_len = block_len; + } + + /* Copy remaining bytes, if any, to last mbuf */ + om->om_len += rem_len; + __asm__ volatile (".syntax unified \n" + " b 2f \n" + "1: ldrb r3, [%[src], %[len]] \n" + " strb r3, [%[dst], %[len]] \n" + "2: subs %[len], #1 \n" + " bpl 1b \n" + : [len] "+l" (rem_len) + : [dst] "l" (dst), [src] "l" (src) + : "r3", "memory" + ); + + /* Copy header */ + memcpy(BLE_MBUF_HDR_PTR(rxpdu), &g_ble_phy_data.rxhdr, + sizeof(struct ble_mbuf_hdr)); +} + +/** + * Called when we want to wait if the radio is in either the rx or tx + * disable states. We want to wait until that state is over before doing + * anything to the radio + */ +static void +nrf_wait_disabled(void) +{ + uint32_t state; + + /* + * RX and TX states have the same values except for 3rd bit (0=RX, 1=TX) so + * we use RX symbols only. + */ + state = NRF_RADIO->STATE & 0x07; + + if (state != RADIO_STATE_STATE_Disabled) { + /* If PHY is in idle state for whatever reason, disable it now */ + if (state == RADIO_STATE_STATE_RxIdle) { + NRF_RADIO->TASKS_DISABLE = 1; + STATS_INC(ble_phy_stats, radio_state_errs); + } + + if (state == RADIO_STATE_STATE_RxDisable) { + /* This will end within a short time (6 usecs). Just poll */ + while (NRF_RADIO->STATE == state) { + /* If this fails, something is really wrong. Should last + * no more than 6 usecs */ + } + } + } +} + +/** + * + * + */ +int +ble_phy_set_start_time(uint32_t cputime, uint8_t rem_usecs) +{ + uint32_t next_cc; + uint32_t cur_cc; + uint32_t cntr; + uint32_t delta; + + /* + * XXX: The TXEN time is 140 usecs but there may be additional delays + * Need to look at this. + */ + + /* + * With the 32.768 kHz crystal, we may need to adjust the RTC compare + * value by 1 tick due to the time it takes for TXEN. The code uses a 5 RTC + * tick offset, which is 152.5 usecs. The TXEN time is 140 usecs. This + * means that with a remainder of 0, TIMER0 should be set to 12 or 13 (as + * TIMER0 counts at 1MHz). A remainder of 19 or more we will need to add + * 1 tick. We dont need to add 1 tick per se, but it does give us slightly + * more time and thus less of a chance to miss a tick. Another note: we + * cant set TIMER0 CC to 0 as the compare wont occur; it must be 1 or more. + * This is why we subtract 18 (as opposed to 19) as rem_uses will be >= 1. + */ + if (rem_usecs <= 18) { + cputime -= 5; + rem_usecs += 12; + } else { + cputime -= 4; + rem_usecs -= 18; + } + + /* + * Can we set the RTC compare to start TIMER0? We can do it if: + * a) Current compare value is not N+1 or N+2 ticks from current + * counter. + * b) The value we want to set is not at least N+2 from current + * counter. + * + * NOTE: since the counter can tick 1 while we do these calculations we + * need to account for it. + */ + next_cc = cputime & 0xffffff; + cur_cc = NRF_RTC0->CC[0]; + cntr = NRF_RTC0->COUNTER; + + delta = (cur_cc - cntr) & 0xffffff; + if ((delta <= 3) && (delta != 0)) { + return -1; + } + delta = (next_cc - cntr) & 0xffffff; + if ((delta & 0x800000) || (delta < 3)) { + return -1; + } + + /* Clear and set TIMER0 to fire off at proper time */ + NRF_TIMER0->TASKS_CLEAR = 1; + NRF_TIMER0->CC[0] = rem_usecs; + NRF_TIMER0->EVENTS_COMPARE[0] = 0; + + /* Set RTC compare to start TIMER0 */ + NRF_RTC0->EVENTS_COMPARE[0] = 0; + NRF_RTC0->CC[0] = next_cc; + NRF_RTC0->EVTENSET = RTC_EVTENSET_COMPARE0_Msk; + + /* Enable PPI */ + NRF_PPI->CHENSET = PPI_CHEN_CH31_Msk; + + /* Store the cputime at which we set the RTC */ + g_ble_phy_data.phy_start_cputime = cputime; + + return 0; +} + +/** + * Function is used to set PPI so that we can time out waiting for a reception + * to occur. This happens for two reasons: we have sent a packet and we are + * waiting for a respons (txrx should be set to ENABLE_TXRX) or we are + * starting a connection event and we are a slave and we are waiting for the + * master to send us a packet (txrx should be set to ENABLE_RX). + * + * NOTE: when waiting for a txrx turn-around, wfr_usecs is not used as there + * is no additional time to wait; we know when we should receive the address of + * the received frame. + * + * @param txrx Flag denoting if this wfr is a txrx turn-around or not. + * @param tx_phy_mode phy mode for last TX (not used on nRF51) + * @param wfr_usecs Amount of usecs to wait. + */ +void +ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs) +{ + uint32_t end_time; + + if (txrx == BLE_PHY_WFR_ENABLE_TXRX) { + /* + * Timeout occurs an IFS time plus time it takes to receive address + * from the transmit end. We add additional time to make sure the + * address event comes before the compare. Note that transmit end + * is captured in CC[2]. I just made up the 16 usecs I add here. + */ + end_time = NRF_TIMER0->CC[2] + BLE_LL_IFS + + ble_phy_mode_pdu_start_off(BLE_PHY_MODE_1M) + 16; + } else { + /* CC[0] is set to when RXEN occurs. */ + end_time = NRF_TIMER0->CC[0] + XCVR_RX_START_DELAY_USECS + wfr_usecs + + ble_phy_mode_pdu_start_off(BLE_PHY_MODE_1M) + BLE_LL_JITTER_USECS; + } + + /* wfr_secs is the time from rxen until timeout */ + NRF_TIMER0->CC[3] = end_time; + NRF_TIMER0->EVENTS_COMPARE[3] = 0; + + /* Enable wait for response PPI */ + NRF_PPI->CHENSET = (PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk); + + /* Enable the disabled interrupt so we time out on events compare */ + NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk; +} + +/** + * Setup transceiver for receive. + */ +static void +ble_phy_rx_xcvr_setup(void) +{ + uint8_t *dptr; + + dptr = (uint8_t *)&g_ble_phy_rx_buf[0]; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + if (g_ble_phy_data.phy_encrypted) { + dptr += 3; + NRF_RADIO->PACKETPTR = (uint32_t)&g_ble_phy_enc_buf[0]; + NRF_CCM->INPTR = (uint32_t)&g_ble_phy_enc_buf[0]; + NRF_CCM->OUTPTR = (uint32_t)dptr; + NRF_CCM->SCRATCHPTR = (uint32_t)&g_nrf_encrypt_scratchpad[0]; + NRF_CCM->MODE = CCM_MODE_MODE_Decryption; + NRF_CCM->CNFPTR = (uint32_t)&g_nrf_ccm_data; + NRF_CCM->SHORTS = 0; + NRF_CCM->EVENTS_ERROR = 0; + NRF_CCM->EVENTS_ENDCRYPT = 0; + NRF_PPI->CHENSET = PPI_CHEN_CH24_Msk | PPI_CHEN_CH25_Msk; + } else { + NRF_RADIO->PACKETPTR = (uint32_t)dptr; + } +#else + NRF_RADIO->PACKETPTR = (uint32_t)dptr; +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + if (g_ble_phy_data.phy_privacy) { + dptr += 3; + NRF_RADIO->PACKETPTR = (uint32_t)dptr; + NRF_RADIO->PCNF0 = (6 << RADIO_PCNF0_LFLEN_Pos) | + (2 << RADIO_PCNF0_S1LEN_Pos) | + (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos); + NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Enabled; + NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0]; + NRF_AAR->SCRATCHPTR = (uint32_t)&g_ble_phy_data.phy_aar_scratch; + NRF_AAR->EVENTS_END = 0; + NRF_AAR->EVENTS_RESOLVED = 0; + NRF_AAR->EVENTS_NOTRESOLVED = 0; + } else { + if (g_ble_phy_data.phy_encrypted == 0) { + NRF_RADIO->PCNF0 = (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos) | + (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos); + /* XXX: do I only need to do this once? Figure out what I can do + once. */ + NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Disabled; + } + } +#endif + + /* Turn off trigger TXEN on output compare match and AAR on bcmatch */ + NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk | PPI_CHEN_CH23_Msk; + + /* Reset the rx started flag. Used for the wait for response */ + g_ble_phy_data.phy_rx_started = 0; + g_ble_phy_data.phy_state = BLE_PHY_STATE_RX; + g_ble_phy_data.rxdptr = dptr; + + /* I want to know when 1st byte received (after address) */ + NRF_RADIO->BCC = 8; /* in bits */ + NRF_RADIO->EVENTS_ADDRESS = 0; + NRF_RADIO->EVENTS_DEVMATCH = 0; + NRF_RADIO->EVENTS_BCMATCH = 0; + NRF_RADIO->EVENTS_RSSIEND = 0; + NRF_RADIO->SHORTS = RADIO_SHORTS_END_DISABLE_Msk | + RADIO_SHORTS_READY_START_Msk | + RADIO_SHORTS_DISABLED_TXEN_Msk | + RADIO_SHORTS_ADDRESS_BCSTART_Msk | + RADIO_SHORTS_ADDRESS_RSSISTART_Msk | + RADIO_SHORTS_DISABLED_RSSISTOP_Msk; + + NRF_RADIO->INTENSET = RADIO_INTENSET_ADDRESS_Msk; +} + +/** + * Called from interrupt context when the transmit ends + * + */ +static void +ble_phy_tx_end_isr(void) +{ + uint8_t was_encrypted; + uint8_t transition; + uint8_t txlen; + uint32_t wfr_time; + + /* If this transmission was encrypted we need to remember it */ + was_encrypted = g_ble_phy_data.phy_encrypted; + (void)was_encrypted; + + /* Better be in TX state! */ + assert(g_ble_phy_data.phy_state == BLE_PHY_STATE_TX); + + /* Clear events and clear interrupt on disabled event */ + NRF_RADIO->EVENTS_DISABLED = 0; + NRF_RADIO->INTENCLR = RADIO_INTENCLR_DISABLED_Msk; + NRF_RADIO->EVENTS_END = 0; + wfr_time = NRF_RADIO->SHORTS; + (void)wfr_time; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + /* + * XXX: not sure what to do. We had a HW error during transmission. + * For now I just count a stat but continue on like all is good. + */ + if (was_encrypted) { + if (NRF_CCM->EVENTS_ERROR) { + STATS_INC(ble_phy_stats, tx_hw_err); + NRF_CCM->EVENTS_ERROR = 0; + } + } +#endif + + /* Call transmit end callback */ + if (g_ble_phy_data.txend_cb) { + g_ble_phy_data.txend_cb(g_ble_phy_data.txend_arg); + } + + transition = g_ble_phy_data.phy_transition; + if (transition == BLE_PHY_TRANSITION_TX_RX) { + /* Packet pointer needs to be reset. */ + ble_phy_rx_xcvr_setup(); + + /* + * Enable the wait for response timer. Note that cc #1 on + * timer 0 contains the transmit start time + */ + txlen = g_ble_phy_data.phy_tx_pyld_len; + if (txlen && was_encrypted) { + txlen += BLE_LL_DATA_MIC_LEN; + } + ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_TXRX, 0, 0); + } else { + /* + * XXX: not sure we need to stop the timer here all the time. Or that + * it should be stopped here. + */ + NRF_TIMER0->TASKS_STOP = 1; + NRF_TIMER0->TASKS_SHUTDOWN = 1; + NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | + PPI_CHEN_CH20_Msk | PPI_CHEN_CH31_Msk; + assert(transition == BLE_PHY_TRANSITION_NONE); + } +} + +static void +ble_phy_rx_end_isr(void) +{ + int rc; + uint8_t *dptr; + uint8_t crcok; + struct ble_mbuf_hdr *ble_hdr; + + /* Clear events and clear interrupt */ + NRF_RADIO->EVENTS_END = 0; + NRF_RADIO->INTENCLR = RADIO_INTENCLR_END_Msk; + + /* Disable automatic RXEN */ + NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk; + + /* Set RSSI and CRC status flag in header */ + ble_hdr = &g_ble_phy_data.rxhdr; + assert(NRF_RADIO->EVENTS_RSSIEND != 0); + ble_hdr->rxinfo.rssi = (-1 * NRF_RADIO->RSSISAMPLE) + + g_ble_phy_data.rx_pwr_compensation; + + dptr = g_ble_phy_data.rxdptr; + + /* Count PHY crc errors and valid packets */ + crcok = (uint8_t)NRF_RADIO->CRCSTATUS; + if (!crcok) { + STATS_INC(ble_phy_stats, rx_crc_err); + } else { + STATS_INC(ble_phy_stats, rx_valid); + ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_CRC_OK; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + if (g_ble_phy_data.phy_encrypted) { + /* Only set MIC failure flag if frame is not zero length */ + if ((dptr[1] != 0) && (NRF_CCM->MICSTATUS == 0)) { + ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_MIC_FAILURE; + } + + /* + * XXX: not sure how to deal with this. This should not + * be a MIC failure but we should not hand it up. I guess + * this is just some form of rx error and that is how we + * handle it? For now, just set CRC error flags + */ + if (NRF_CCM->EVENTS_ERROR) { + STATS_INC(ble_phy_stats, rx_hw_err); + ble_hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_CRC_OK; + } + + /* + * XXX: This is a total hack work-around for now but I dont + * know what else to do. If ENDCRYPT is not set and we are + * encrypted we need to not trust this frame and drop it. + */ + if (NRF_CCM->EVENTS_ENDCRYPT == 0) { + STATS_INC(ble_phy_stats, rx_hw_err); + ble_hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_CRC_OK; + } + } +#endif + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + if (g_ble_phy_data.phy_encrypted || g_ble_phy_data.phy_privacy) { + /* + * XXX: This is a horrible ugly hack to deal with the RAM S1 byte. + * This should get fixed as we should not be handing up the header + * and length as part of the pdu. + */ + dptr[2] = dptr[1]; + dptr[1] = dptr[0]; + ++dptr; + } +#endif + rc = ble_ll_rx_end(dptr, ble_hdr); + if (rc < 0) { + ble_phy_disable(); + } +} + +static void +ble_phy_rx_start_isr(void) +{ + int rc; + uint32_t state; + uint32_t usecs; + uint32_t ticks; + struct ble_mbuf_hdr *ble_hdr; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + uint8_t *dptr; + + dptr = (uint8_t *)&g_ble_phy_rx_buf[0]; +#endif + + /* Clear events and clear interrupt */ + NRF_RADIO->EVENTS_ADDRESS = 0; + + /* Clear wfr timer channels and DISABLED interrupt */ + NRF_RADIO->INTENCLR = RADIO_INTENCLR_DISABLED_Msk | RADIO_INTENCLR_ADDRESS_Msk; + NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk; + + /* Initialize flags, channel and state in ble header at rx start */ + ble_hdr = &g_ble_phy_data.rxhdr; + ble_hdr->rxinfo.flags = ble_ll_state_get(); + ble_hdr->rxinfo.channel = g_ble_phy_data.phy_chan; + ble_hdr->rxinfo.handle = 0; + ble_hdr->rxinfo.phy = BLE_PHY_1M; + ble_hdr->rxinfo.phy_mode = BLE_PHY_MODE_1M; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + ble_hdr->rxinfo.user_data = NULL; +#endif + + /* + * Calculate receive start time. + * + * XXX: possibly use other routine with remainder! + */ + usecs = NRF_TIMER0->CC[1] - ble_phy_mode_pdu_start_off(BLE_PHY_MODE_1M); + ticks = os_cputime_usecs_to_ticks(usecs); + ble_hdr->rem_usecs = usecs - os_cputime_ticks_to_usecs(ticks); + if (ble_hdr->rem_usecs == 31) { + ble_hdr->rem_usecs = 0; + ++ticks; + } + ble_hdr->beg_cputime = g_ble_phy_data.phy_start_cputime + ticks; + + /* Wait to get 1st byte of frame */ + while (1) { + state = NRF_RADIO->STATE; + if (NRF_RADIO->EVENTS_BCMATCH != 0) { + break; + } + + /* + * If state is disabled, we should have the BCMATCH. If not, + * something is wrong! + */ + if (state == RADIO_STATE_STATE_Disabled) { + NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL; + NRF_RADIO->SHORTS = 0; + return; + } + } + + /* Call Link Layer receive start function */ + rc = ble_ll_rx_start(g_ble_phy_data.rxdptr, g_ble_phy_data.phy_chan, + &g_ble_phy_data.rxhdr); + if (rc >= 0) { + /* Set rx started flag and enable rx end ISR */ + g_ble_phy_data.phy_rx_started = 1; + NRF_RADIO->INTENSET = RADIO_INTENSET_END_Msk; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + /* Must start aar if we need to */ + if (g_ble_phy_data.phy_privacy) { + NRF_RADIO->EVENTS_BCMATCH = 0; + NRF_PPI->CHENSET = PPI_CHEN_CH23_Msk; + /* + * Setup AAR to resolve AdvA and trigger it after complete address + * is received, i.e. after PDU header and AdvA is received. + * + * AdvA starts at 4th octet in receive buffer, after S0, len and S1 + * fields. + * + * In case of extended advertising AdvA is located after extended + * header (+2 octets). + */ + if (BLE_MBUF_HDR_EXT_ADV(&g_ble_phy_data.rxhdr)) { + NRF_AAR->ADDRPTR = (uint32_t)(dptr + 5); + NRF_RADIO->BCC = (BLE_DEV_ADDR_LEN + BLE_LL_PDU_HDR_LEN + 2) * 8; + + } else { + NRF_AAR->ADDRPTR = (uint32_t)(dptr + 3); + NRF_RADIO->BCC = (BLE_DEV_ADDR_LEN + BLE_LL_PDU_HDR_LEN) * 8; + } + } +#endif + } else { + /* Disable PHY */ + ble_phy_disable(); + STATS_INC(ble_phy_stats, rx_aborts); + } + + /* Count rx starts */ + STATS_INC(ble_phy_stats, rx_starts); +} + +static void +ble_phy_isr(void) +{ + uint32_t irq_en; + + os_trace_isr_enter(); + + /* Read irq register to determine which interrupts are enabled */ + irq_en = NRF_RADIO->INTENCLR; + + /* + * NOTE: order of checking is important! Possible, if things get delayed, + * we have both an ADDRESS and DISABLED interrupt in rx state. If we get + * an address, we disable the DISABLED interrupt. + */ + + /* We get this if we have started to receive a frame */ + if ((irq_en & RADIO_INTENCLR_ADDRESS_Msk) && NRF_RADIO->EVENTS_ADDRESS) { + irq_en &= ~RADIO_INTENCLR_DISABLED_Msk; + ble_phy_rx_start_isr(); + } + + /* Check for disabled event. This only happens for transmits now */ + if ((irq_en & RADIO_INTENCLR_DISABLED_Msk) && NRF_RADIO->EVENTS_DISABLED) { + if (g_ble_phy_data.phy_state == BLE_PHY_STATE_RX) { + NRF_RADIO->EVENTS_DISABLED = 0; + ble_ll_wfr_timer_exp(NULL); + } else { + ble_phy_tx_end_isr(); + } + } + + /* Receive packet end (we dont enable this for transmit) */ + if ((irq_en & RADIO_INTENCLR_END_Msk) && NRF_RADIO->EVENTS_END) { + ble_phy_rx_end_isr(); + } + + /* Ensures IRQ is cleared */ + irq_en = NRF_RADIO->SHORTS; + + /* Count # of interrupts */ + STATS_INC(ble_phy_stats, phy_isrs); + + os_trace_isr_exit(); +} + +/** + * ble phy init + * + * Initialize the PHY. + * + * @return int 0: success; PHY error code otherwise + */ +int +ble_phy_init(void) +{ + int rc; + + /* Set phy channel to an invalid channel so first set channel works */ + g_ble_phy_data.phy_chan = BLE_PHY_NUM_CHANS; + + g_ble_phy_data.rx_pwr_compensation = 0; + + /* Toggle peripheral power to reset (just in case) */ + NRF_RADIO->POWER = 0; + NRF_RADIO->POWER = 1; + + /* Disable all interrupts */ + NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL; + + /* Set configuration registers */ + NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_1Mbit; + NRF_RADIO->PCNF0 = (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos) | + (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos); + /* XXX: should maxlen be 251 for encryption? */ + NRF_RADIO->PCNF1 = NRF_MAXLEN | + (RADIO_PCNF1_ENDIAN_Little << RADIO_PCNF1_ENDIAN_Pos) | + (NRF_BALEN << RADIO_PCNF1_BALEN_Pos) | + RADIO_PCNF1_WHITEEN_Msk; + + /* Set base0 with the advertising access address */ + NRF_RADIO->BASE0 = (BLE_ACCESS_ADDR_ADV << 8) & 0xFFFFFF00; + NRF_RADIO->PREFIX0 = (BLE_ACCESS_ADDR_ADV >> 24) & 0xFF; + + /* Configure the CRC registers */ + NRF_RADIO->CRCCNF = RADIO_CRCCNF_SKIPADDR_Msk | RADIO_CRCCNF_LEN_Three; + + /* Configure BLE poly */ + NRF_RADIO->CRCPOLY = 0x0100065B; + + /* Configure IFS */ + NRF_RADIO->TIFS = BLE_LL_IFS; + + /* Captures tx/rx start in timer0 cc 1 and tx/rx end in timer0 cc 2 */ + NRF_PPI->CHENSET = PPI_CHEN_CH26_Msk | PPI_CHEN_CH27_Msk; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + NRF_CCM->INTENCLR = 0xffffffff; + NRF_CCM->SHORTS = CCM_SHORTS_ENDKSGEN_CRYPT_Msk; + NRF_CCM->EVENTS_ERROR = 0; + memset(g_nrf_encrypt_scratchpad, 0, sizeof(g_nrf_encrypt_scratchpad)); +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + g_ble_phy_data.phy_aar_scratch = 0; + NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0]; + NRF_AAR->INTENCLR = 0xffffffff; + NRF_AAR->EVENTS_END = 0; + NRF_AAR->EVENTS_RESOLVED = 0; + NRF_AAR->EVENTS_NOTRESOLVED = 0; + NRF_AAR->NIRK = 0; +#endif + + /* TIMER0 setup for PHY when using RTC */ + NRF_TIMER0->TASKS_STOP = 1; + NRF_TIMER0->TASKS_SHUTDOWN = 1; + NRF_TIMER0->BITMODE = 3; /* 32-bit timer */ + NRF_TIMER0->MODE = 0; /* Timer mode */ + NRF_TIMER0->PRESCALER = 4; /* gives us 1 MHz */ + + /* + * PPI setup. + * Channel 4: Captures TIMER0 in CC[3] when EVENTS_ADDRESS occurs. Used + * to cancel the wait for response timer. + * Channel 5: TIMER0 CC[3] to TASKS_DISABLE on radio. This is the wait + * for response timer. + */ + NRF_PPI->CH[4].EEP = (uint32_t)&(NRF_RADIO->EVENTS_ADDRESS); + NRF_PPI->CH[4].TEP = (uint32_t)&(NRF_TIMER0->TASKS_CAPTURE[3]); + NRF_PPI->CH[5].EEP = (uint32_t)&(NRF_TIMER0->EVENTS_COMPARE[3]); + NRF_PPI->CH[5].TEP = (uint32_t)&(NRF_RADIO->TASKS_DISABLE); + + /* Set isr in vector table and enable interrupt */ +#ifndef RIOT_VERSION + NVIC_SetPriority(RADIO_IRQn, 0); +#endif +#if MYNEWT + NVIC_SetVector(RADIO_IRQn, (uint32_t)ble_phy_isr); +#else + ble_npl_hw_set_isr(RADIO_IRQn, ble_phy_isr); +#endif + NVIC_EnableIRQ(RADIO_IRQn); + + /* Register phy statistics */ + if (!g_ble_phy_data.phy_stats_initialized) { + rc = stats_init_and_reg(STATS_HDR(ble_phy_stats), + STATS_SIZE_INIT_PARMS(ble_phy_stats, + STATS_SIZE_32), + STATS_NAME_INIT_PARMS(ble_phy_stats), + "ble_phy"); + assert(rc == 0); + + g_ble_phy_data.phy_stats_initialized = 1; + } + + return 0; +} + +/** + * Puts the phy into receive mode. + * + * @return int 0: success; BLE Phy error code otherwise + */ +int +ble_phy_rx(void) +{ + /* Check radio state */ + nrf_wait_disabled(); + if (NRF_RADIO->STATE != RADIO_STATE_STATE_Disabled) { + ble_phy_disable(); + STATS_INC(ble_phy_stats, radio_state_errs); + return BLE_PHY_ERR_RADIO_STATE; + } + + /* Make sure all interrupts are disabled */ + NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL; + + /* Clear events prior to enabling receive */ + NRF_RADIO->EVENTS_END = 0; + NRF_RADIO->EVENTS_DISABLED = 0; + + /* Setup for rx */ + ble_phy_rx_xcvr_setup(); + + /* Start the receive task in the radio if not automatically going to rx */ + if ((NRF_PPI->CHEN & PPI_CHEN_CH21_Msk) == 0) { + NRF_RADIO->TASKS_RXEN = 1; + } + + return 0; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) +/** + * Called to enable encryption at the PHY. Note that this state will persist + * in the PHY; in other words, if you call this function you have to call + * disable so that future PHY transmits/receives will not be encrypted. + * + * @param pkt_counter + * @param iv + * @param key + * @param is_master + */ +void +ble_phy_encrypt_enable(uint64_t pkt_counter, uint8_t *iv, uint8_t *key, + uint8_t is_master) +{ + memcpy(g_nrf_ccm_data.key, key, 16); + g_nrf_ccm_data.pkt_counter = pkt_counter; + memcpy(g_nrf_ccm_data.iv, iv, 8); + g_nrf_ccm_data.dir_bit = is_master; + g_ble_phy_data.phy_encrypted = 1; + + /* Encryption uses LFLEN=5, S1LEN = 3. */ + NRF_RADIO->PCNF0 = (5 << RADIO_PCNF0_LFLEN_Pos) | + (3 << RADIO_PCNF0_S1LEN_Pos) | + (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos); + + /* Enable the module (AAR cannot be on while CCM on) */ + NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Disabled; + NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Enabled; +} + +void +ble_phy_encrypt_set_pkt_cntr(uint64_t pkt_counter, int dir) +{ + g_nrf_ccm_data.pkt_counter = pkt_counter; + g_nrf_ccm_data.dir_bit = dir; +} + +void +ble_phy_encrypt_disable(void) +{ + NRF_PPI->CHENCLR = (PPI_CHEN_CH24_Msk | PPI_CHEN_CH25_Msk); + NRF_CCM->TASKS_STOP = 1; + NRF_CCM->EVENTS_ERROR = 0; + NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Disabled; + + /* Switch back to normal length */ + NRF_RADIO->PCNF0 = (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos) | + (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos); + + g_ble_phy_data.phy_encrypted = 0; +} +#endif + +void +ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg) +{ + /* Set transmit end callback and arg */ + g_ble_phy_data.txend_cb = txend_cb; + g_ble_phy_data.txend_arg = arg; +} + +/** + * Called to set the start time of a transmission. + * + * This function is called to set the start time when we are not going from + * rx to tx automatically. + * + * NOTE: care must be taken when calling this function. The channel should + * already be set. + * + * @param cputime This is the tick at which the 1st bit of the preamble + * should be transmitted + * @param rem_usecs This is used only when the underlying timing uses a 32.768 + * kHz crystal. It is the # of usecs from the cputime tick + * at which the first bit of the preamble should be + * transmitted. + * @return int + */ +int +ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs) +{ + int rc; + + ble_phy_trace_u32x2(BLE_PHY_TRACE_ID_START_TX, cputime, rem_usecs); + + /* XXX: This should not be necessary, but paranoia is good! */ + /* Clear timer0 compare to RXEN since we are transmitting */ + NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk; + + /* + * XXX: The TXEN time is 140 usecs but there may be additional delays + * Need to look at this. + */ + if (ble_phy_set_start_time(cputime, rem_usecs) != 0) { + STATS_INC(ble_phy_stats, tx_late); + ble_phy_disable(); + rc = BLE_PHY_ERR_TX_LATE; + } else { + /* Enable PPI to automatically start TXEN */ + NRF_PPI->CHENSET = PPI_CHEN_CH20_Msk; + rc = 0; + } + return rc; +} +/** + * Called to set the start time of a reception + * + * This function acts a bit differently than transmit. If we are late getting + * here we will still attempt to receive. + * + * NOTE: care must be taken when calling this function. The channel should + * already be set. + * + * @param cputime + * + * @return int + */ +int +ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs) +{ + int rc; + + ble_phy_trace_u32x2(BLE_PHY_TRACE_ID_START_RX, cputime, rem_usecs); + + /* XXX: This should not be necessary, but paranoia is good! */ + /* Clear timer0 compare to TXEN since we are transmitting */ + NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk; + + /* + * XXX: The RXEN time is 138 usecs but there may be additional delays + * Need to look at this. + */ + if (ble_phy_set_start_time(cputime, rem_usecs) != 0) { + STATS_INC(ble_phy_stats, rx_late); + NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk; + NRF_RADIO->TASKS_RXEN = 1; + rc = BLE_PHY_ERR_RX_LATE; + } else { + /* Enable PPI to automatically start RXEN */ + NRF_PPI->CHENSET = PPI_CHEN_CH21_Msk; + + /* Start rx */ + rc = ble_phy_rx(); + } + return rc; +} + +int +ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans) +{ + int rc; + uint8_t *dptr; + uint8_t payload_len; + uint8_t payload_off; + uint8_t hdr_byte; + uint32_t state; + uint32_t shortcuts; + + /* + * This check is to make sure that the radio is not in a state where + * it is moving to disabled state. If so, let it get there. + */ + nrf_wait_disabled(); + + /* + * XXX: Although we may not have to do this here, I clear all the PPI + * that should not be used when transmitting. Some of them are only enabled + * if encryption and/or privacy is on, but I dont care. Better to be + * paranoid, and if you are going to clear one, might as well clear them + * all. + */ + NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | PPI_CHEN_CH23_Msk | + PPI_CHEN_CH25_Msk; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + if (g_ble_phy_data.phy_encrypted) { + /* RAM representation has S0, LENGTH and S1 fields. (3 bytes) */ + dptr = (uint8_t *)&g_ble_phy_enc_buf[0]; + payload_off = 3; + + NRF_CCM->SHORTS = 1; + NRF_CCM->INPTR = (uint32_t)&g_ble_phy_enc_buf[0]; + NRF_CCM->OUTPTR = (uint32_t)&g_ble_phy_tx_buf[0]; + NRF_CCM->SCRATCHPTR = (uint32_t)&g_nrf_encrypt_scratchpad[0]; + NRF_CCM->EVENTS_ERROR = 0; + NRF_CCM->MODE = CCM_MODE_MODE_Encryption; + NRF_CCM->CNFPTR = (uint32_t)&g_nrf_ccm_data; + NRF_PPI->CHENSET = PPI_CHEN_CH24_Msk; + } else { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + /* Reconfigure PCNF0 */ + NRF_RADIO->PCNF0 = (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos) | + (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos); + NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0]; +#endif + /* RAM representation has S0 and LENGTH fields (2 bytes) */ + dptr = (uint8_t *)&g_ble_phy_tx_buf[0]; + payload_off = 2; + } +#else + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + /* Reconfigure PCNF0 */ + NRF_RADIO->PCNF0 = (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos) | + (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos); +#endif + + /* RAM representation has S0 and LENGTH fields (2 bytes) */ + dptr = (uint8_t *)&g_ble_phy_tx_buf[0]; + payload_off = 2; +#endif + + NRF_RADIO->PACKETPTR = (uint32_t)&g_ble_phy_tx_buf[0]; + + /* Clear the ready, end and disabled events */ + NRF_RADIO->EVENTS_READY = 0; + NRF_RADIO->EVENTS_END = 0; + NRF_RADIO->EVENTS_DISABLED = 0; + + /* Enable shortcuts for transmit start/end. */ + shortcuts = RADIO_SHORTS_END_DISABLE_Msk | RADIO_SHORTS_READY_START_Msk; + if (end_trans == BLE_PHY_TRANSITION_TX_RX) { + shortcuts |= RADIO_SHORTS_DISABLED_RXEN_Msk; + } + NRF_RADIO->SHORTS = shortcuts; + NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk; + + /* Set PDU payload */ + payload_len = pducb(&dptr[payload_off], pducb_arg, &hdr_byte); + + /* Set PDU header */ + dptr[0] = hdr_byte; + dptr[1] = payload_len; + if (payload_off > 2) { + dptr[2] = 0; + } + + /* Set the PHY transition */ + g_ble_phy_data.phy_transition = end_trans; + + /* Set transmitted payload length */ + g_ble_phy_data.phy_tx_pyld_len = payload_len; + + /* If we already started transmitting, abort it! */ + state = NRF_RADIO->STATE; + if (state != RADIO_STATE_STATE_Tx) { + + /* Set phy state to transmitting and count packet statistics */ + g_ble_phy_data.phy_state = BLE_PHY_STATE_TX; + STATS_INC(ble_phy_stats, tx_good); + STATS_INCN(ble_phy_stats, tx_bytes, payload_len + BLE_LL_PDU_HDR_LEN); + rc = BLE_ERR_SUCCESS; + } else { + ble_phy_disable(); + STATS_INC(ble_phy_stats, tx_late); + rc = BLE_PHY_ERR_RADIO_STATE; + } + + return rc; +} + +/** + * ble phy txpwr set + * + * Set the transmit output power (in dBm). + * + * NOTE: If the output power specified is within the BLE limits but outside + * the chip limits, we "rail" the power level so we dont exceed the min/max + * chip values. + * + * @param dbm Power output in dBm. + * + * @return int 0: success; anything else is an error + */ +int +ble_phy_txpwr_set(int dbm) +{ + /* Check valid range */ + assert(dbm <= BLE_PHY_MAX_PWR_DBM); + + /* "Rail" power level if outside supported range */ + if (dbm > NRF_TX_PWR_MAX_DBM) { + dbm = NRF_TX_PWR_MAX_DBM; + } else { + if (dbm < NRF_TX_PWR_MIN_DBM) { + dbm = NRF_TX_PWR_MIN_DBM; + } + } + + NRF_RADIO->TXPOWER = dbm; + g_ble_phy_data.phy_txpwr_dbm = dbm; + + return 0; +} + +/** + * ble phy txpwr round + * + * Get the rounded transmit output power (in dBm). + * + * @param dbm Power output in dBm. + * + * @return int Rounded power in dBm + */ +int ble_phy_txpower_round(int dbm) +{ + /* "Rail" power level if outside supported range */ + if (dbm > NRF_TX_PWR_MAX_DBM) { + dbm = NRF_TX_PWR_MAX_DBM; + } else { + if (dbm < NRF_TX_PWR_MIN_DBM) { + dbm = NRF_TX_PWR_MIN_DBM; + } + } + + return dbm; +} + +/** + * ble phy txpwr get + * + * Get the transmit power. + * + * @return int The current PHY transmit power, in dBm + */ +int +ble_phy_txpwr_get(void) +{ + return g_ble_phy_data.phy_txpwr_dbm; +} + +void +ble_phy_set_rx_pwr_compensation(int8_t compensation) +{ + g_ble_phy_data.rx_pwr_compensation = compensation; +} + +/** + * ble phy setchan + * + * Sets the logical frequency of the transceiver. The input parameter is the + * BLE channel index (0 to 39, inclusive). The NRF frequency register works like + * this: logical frequency = 2400 + FREQ (MHz). + * + * Thus, to get a logical frequency of 2402 MHz, you would program the + * FREQUENCY register to 2. + * + * @param chan This is the Data Channel Index or Advertising Channel index + * + * @return int 0: success; PHY error code otherwise + */ +int +ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit) +{ + uint32_t prefix; + + assert(chan < BLE_PHY_NUM_CHANS); + + /* Check for valid channel range */ + if (chan >= BLE_PHY_NUM_CHANS) { + return BLE_PHY_ERR_INV_PARAM; + } + + /* Get correct frequency */ + if (chan < BLE_PHY_NUM_DATA_CHANS) { + /* Set current access address */ + g_ble_phy_data.phy_access_address = access_addr; + + /* Configure logical address 1 and crcinit */ + prefix = NRF_RADIO->PREFIX0; + prefix &= 0xffff00ff; + prefix |= ((access_addr >> 24) & 0xFF) << 8; + NRF_RADIO->BASE1 = (access_addr << 8) & 0xFFFFFF00; + NRF_RADIO->PREFIX0 = prefix; + NRF_RADIO->TXADDRESS = 1; + NRF_RADIO->RXADDRESSES = (1 << 1); + NRF_RADIO->CRCINIT = crcinit; + } else { + /* Logical adddress 0 preconfigured */ + NRF_RADIO->TXADDRESS = 0; + NRF_RADIO->RXADDRESSES = (1 << 0); + NRF_RADIO->CRCINIT = BLE_LL_CRCINIT_ADV; + + /* Set current access address */ + g_ble_phy_data.phy_access_address = BLE_ACCESS_ADDR_ADV; + } + + /* Set the frequency and the data whitening initial value */ + g_ble_phy_data.phy_chan = chan; + NRF_RADIO->FREQUENCY = g_ble_phy_chan_freq[chan]; + NRF_RADIO->DATAWHITEIV = chan; + + return 0; +} + +/** + * Stop the timer used to count microseconds when using RTC for cputime + */ +static void +ble_phy_stop_usec_timer(void) +{ + NRF_TIMER0->TASKS_STOP = 1; + NRF_TIMER0->TASKS_SHUTDOWN = 1; + NRF_RTC0->EVTENCLR = RTC_EVTENSET_COMPARE0_Msk; +} + +/** + * ble phy disable irq and ppi + * + * This routine is to be called when reception was stopped due to either a + * wait for response timeout or a packet being received and the phy is to be + * restarted in receive mode. Generally, the disable routine is called to stop + * the phy. + */ +static void +ble_phy_disable_irq_and_ppi(void) +{ + NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL; + NRF_RADIO->SHORTS = 0; + NRF_RADIO->TASKS_DISABLE = 1; + NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | PPI_CHEN_CH20_Msk | + PPI_CHEN_CH21_Msk | PPI_CHEN_CH23_Msk | PPI_CHEN_CH24_Msk | + PPI_CHEN_CH25_Msk | PPI_CHEN_CH31_Msk; + NVIC_ClearPendingIRQ(RADIO_IRQn); + g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE; +} + +void +ble_phy_restart_rx(void) +{ + ble_phy_stop_usec_timer(); + ble_phy_disable_irq_and_ppi(); + ble_phy_rx(); +} + +/** + * ble phy disable + * + * Disables the PHY. This should be called when an event is over. It stops + * the usec timer (if used), disables interrupts, disables the RADIO, disables + * PPI and sets state to idle. + */ +void +ble_phy_disable(void) +{ + ble_phy_trace_void(BLE_PHY_TRACE_ID_DISABLE); + + ble_phy_stop_usec_timer(); + ble_phy_disable_irq_and_ppi(); +} + +/* Gets the current access address */ +uint32_t ble_phy_access_addr_get(void) +{ + return g_ble_phy_data.phy_access_address; +} + +/** + * Return the phy state + * + * @return int The current PHY state. + */ +int +ble_phy_state_get(void) +{ + return g_ble_phy_data.phy_state; +} + +/** + * Called to see if a reception has started + * + * @return int + */ +int +ble_phy_rx_started(void) +{ + return g_ble_phy_data.phy_rx_started; +} + +/** + * Return the transceiver state + * + * @return int transceiver state. + */ +uint8_t +ble_phy_xcvr_state_get(void) +{ + uint32_t state; + state = NRF_RADIO->STATE; + return (uint8_t)state; +} + +/** + * Called to return the maximum data pdu payload length supported by the + * phy. For this chip, if encryption is enabled, the maximum payload is 27 + * bytes. + * + * @return uint8_t Maximum data channel PDU payload size supported + */ +uint8_t +ble_phy_max_data_pdu_pyld(void) +{ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + return NRF_MAX_ENCRYPTED_PYLD_LEN; +#else + return BLE_LL_DATA_PDU_MAX_PYLD; +#endif +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) +void +ble_phy_resolv_list_enable(void) +{ + NRF_AAR->NIRK = (uint32_t)g_nrf_num_irks; + g_ble_phy_data.phy_privacy = 1; +} + +void +ble_phy_resolv_list_disable(void) +{ + g_ble_phy_data.phy_privacy = 0; +} +#endif + +void +ble_phy_rfclk_enable(void) +{ +#if MYNEWT + nrf51_clock_hfxo_request(); +#else + NRF_CLOCK->TASKS_HFCLKSTART = 1; +#endif +} + +void +ble_phy_rfclk_disable(void) +{ +#if MYNEWT + nrf51_clock_hfxo_release(); +#else + NRF_CLOCK->TASKS_HFCLKSTOP = 1; +#endif +} +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/include/ble/xcvr.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/include/ble/xcvr.h new file mode 100644 index 000000000..fd8e1e898 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/include/ble/xcvr.h @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#if defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) + +#ifndef H_BLE_XCVR_ +#define H_BLE_XCVR_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define XCVR_RX_RADIO_RAMPUP_USECS (40) +#define XCVR_TX_RADIO_RAMPUP_USECS (40) + +/* + * NOTE: we have to account for the RTC output compare issue. We want it to be + * 5 ticks. + */ +#define XCVR_PROC_DELAY_USECS (153) +#define XCVR_RX_START_DELAY_USECS (XCVR_RX_RADIO_RAMPUP_USECS) +#define XCVR_TX_START_DELAY_USECS (XCVR_TX_RADIO_RAMPUP_USECS) +#define XCVR_TX_SCHED_DELAY_USECS \ + (XCVR_TX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS) +#define XCVR_RX_SCHED_DELAY_USECS \ + (XCVR_RX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS) + +/* + * Define HW whitelist size. This is the total possible whitelist size; + * not necessarily the size that will be used (may be smaller) + */ +#define BLE_HW_WHITE_LIST_SIZE (8) + +#ifdef __cplusplus +} +#endif + +#endif /* H_BLE_XCVR_ */ +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/pkg.yml new file mode 100644 index 000000000..a1ff457e6 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/pkg.yml @@ -0,0 +1,31 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: nimble/drivers/nrf52 +pkg.description: BLE driver for nRF52 systems. +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - ble + - bluetooth + +pkg.apis: ble_driver +pkg.deps: + - nimble + - nimble/controller diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_hw.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_hw.c new file mode 100644 index 000000000..400fddf6f --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_hw.c @@ -0,0 +1,491 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#if defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) + +#include +#include +#include +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "../include/ble/xcvr.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/include/nimble/nimble_opt.h" +#include "nrf.h" +#include "nimble/nimble/controller/include/controller/ble_hw.h" +#if MYNEWT +#include "mcu/cmsis_nvic.h" +#else +#include "core_cm4.h" +#include "nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h" +#endif +#include "nimble/porting/nimble/include/os/os_trace_api.h" + +/* Total number of resolving list elements */ +#define BLE_HW_RESOLV_LIST_SIZE (16) + +/* We use this to keep track of which entries are set to valid addresses */ +static uint8_t g_ble_hw_whitelist_mask; + +/* Random number generator isr callback */ +ble_rng_isr_cb_t g_ble_rng_isr_cb; + +/* If LL privacy is enabled, allocate memory for AAR */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + +/* The NRF51 supports up to 16 IRK entries */ +#if (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE) < 16) +#define NRF_IRK_LIST_ENTRIES (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE)) +#else +#define NRF_IRK_LIST_ENTRIES (16) +#endif + +/* NOTE: each entry is 16 bytes long. */ +uint32_t g_nrf_irk_list[NRF_IRK_LIST_ENTRIES * 4]; + +/* Current number of IRK entries */ +uint8_t g_nrf_num_irks; + +#endif + +/* Returns public device address or -1 if not present */ +int +ble_hw_get_public_addr(ble_addr_t *addr) +{ + uint32_t addr_high; + uint32_t addr_low; + + /* Does FICR have a public address */ + if ((NRF_FICR->DEVICEADDRTYPE & 1) != 0) { + return -1; + } + + /* Copy into device address. We can do this because we know platform */ + addr_low = NRF_FICR->DEVICEADDR[0]; + addr_high = NRF_FICR->DEVICEADDR[1]; + memcpy(addr->val, &addr_low, 4); + memcpy(&addr->val[4], &addr_high, 2); + addr->type = BLE_ADDR_PUBLIC; + + return 0; +} + +/* Returns random static address or -1 if not present */ +int +ble_hw_get_static_addr(ble_addr_t *addr) +{ + int rc; + + if ((NRF_FICR->DEVICEADDRTYPE & 1) == 1) { + memcpy(addr->val, (void *)&NRF_FICR->DEVICEADDR[0], 4); + memcpy(&addr->val[4], (void *)&NRF_FICR->DEVICEADDR[1], 2); + addr->val[5] |= 0xc0; + addr->type = BLE_ADDR_RANDOM; + rc = 0; + } else { + rc = -1; + } + + return rc; +} + +/** + * Clear the whitelist + * + * @return int + */ +void +ble_hw_whitelist_clear(void) +{ + NRF_RADIO->DACNF = 0; + g_ble_hw_whitelist_mask = 0; +} + +/** + * Add a device to the hw whitelist + * + * @param addr + * @param addr_type + * + * @return int 0: success, BLE error code otherwise + */ +int +ble_hw_whitelist_add(const uint8_t *addr, uint8_t addr_type) +{ + int i; + uint32_t mask; + + /* Find first ununsed device address match element */ + mask = 0x01; + for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) { + if ((mask & g_ble_hw_whitelist_mask) == 0) { + NRF_RADIO->DAB[i] = get_le32(addr); + NRF_RADIO->DAP[i] = get_le16(addr + 4); + if (addr_type == BLE_ADDR_RANDOM) { + NRF_RADIO->DACNF |= (mask << 8); + } + g_ble_hw_whitelist_mask |= mask; + return BLE_ERR_SUCCESS; + } + mask <<= 1; + } + + return BLE_ERR_MEM_CAPACITY; +} + +/** + * Remove a device from the hw whitelist + * + * @param addr + * @param addr_type + * + */ +void +ble_hw_whitelist_rmv(const uint8_t *addr, uint8_t addr_type) +{ + int i; + uint8_t cfg_addr; + uint16_t dap; + uint16_t txadd; + uint32_t dab; + uint32_t mask; + + /* Find first ununsed device address match element */ + dab = get_le32(addr); + dap = get_le16(addr + 4); + txadd = NRF_RADIO->DACNF >> 8; + mask = 0x01; + for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) { + if (mask & g_ble_hw_whitelist_mask) { + if ((dab == NRF_RADIO->DAB[i]) && (dap == NRF_RADIO->DAP[i])) { + cfg_addr = txadd & mask; + if (addr_type == BLE_ADDR_RANDOM) { + if (cfg_addr != 0) { + break; + } + } else { + if (cfg_addr == 0) { + break; + } + } + } + } + mask <<= 1; + } + + if (i < BLE_HW_WHITE_LIST_SIZE) { + g_ble_hw_whitelist_mask &= ~mask; + NRF_RADIO->DACNF &= ~mask; + } +} + +/** + * Returns the size of the whitelist in HW + * + * @return int Number of devices allowed in whitelist + */ +uint8_t +ble_hw_whitelist_size(void) +{ + return BLE_HW_WHITE_LIST_SIZE; +} + +/** + * Enable the whitelisted devices + */ +void +ble_hw_whitelist_enable(void) +{ + /* Enable the configured device addresses */ + NRF_RADIO->DACNF |= g_ble_hw_whitelist_mask; +} + +/** + * Disables the whitelisted devices + */ +void +ble_hw_whitelist_disable(void) +{ + /* Disable all whitelist devices */ + NRF_RADIO->DACNF &= 0x0000ff00; +} + +/** + * Boolean function which returns true ('1') if there is a match on the + * whitelist. + * + * @return int + */ +int +ble_hw_whitelist_match(void) +{ + return (int)NRF_RADIO->EVENTS_DEVMATCH; +} + +/* Encrypt data */ +int +ble_hw_encrypt_block(struct ble_encryption_block *ecb) +{ + int rc; + uint32_t end; + uint32_t err; + + /* Stop ECB */ + NRF_ECB->TASKS_STOPECB = 1; + /* XXX: does task stop clear these counters? Anyway to do this quicker? */ + NRF_ECB->EVENTS_ENDECB = 0; + NRF_ECB->EVENTS_ERRORECB = 0; + NRF_ECB->ECBDATAPTR = (uint32_t)ecb; + + /* Start ECB */ + NRF_ECB->TASKS_STARTECB = 1; + + /* Wait till error or done */ + rc = 0; + while (1) { + end = NRF_ECB->EVENTS_ENDECB; + err = NRF_ECB->EVENTS_ERRORECB; + if (end || err) { + if (err) { + rc = -1; + } + break; + } + } + + return rc; +} + +/** + * Random number generator ISR. + */ +static void +ble_rng_isr(void) +{ + uint8_t rnum; + + os_trace_isr_enter(); + + /* No callback? Clear and disable interrupts */ + if (g_ble_rng_isr_cb == NULL) { + NRF_RNG->INTENCLR = 1; + NRF_RNG->EVENTS_VALRDY = 0; + (void)NRF_RNG->SHORTS; + os_trace_isr_exit(); + return; + } + + /* If there is a value ready grab it */ + if (NRF_RNG->EVENTS_VALRDY) { + NRF_RNG->EVENTS_VALRDY = 0; + rnum = (uint8_t)NRF_RNG->VALUE; + (*g_ble_rng_isr_cb)(rnum); + } + + os_trace_isr_exit(); +} + +/** + * Initialize the random number generator + * + * @param cb + * @param bias + * + * @return int + */ +int +ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias) +{ + /* Set bias */ + if (bias) { + NRF_RNG->CONFIG = 1; + } else { + NRF_RNG->CONFIG = 0; + } + + /* If we were passed a function pointer we need to enable the interrupt */ + if (cb != NULL) { +#ifndef RIOT_VERSION + NVIC_SetPriority(RNG_IRQn, (1 << __NVIC_PRIO_BITS) - 1); +#endif +#if MYNEWT + NVIC_SetVector(RNG_IRQn, (uint32_t)ble_rng_isr); +#else + ble_npl_hw_set_isr(RNG_IRQn, ble_rng_isr); +#endif + NVIC_EnableIRQ(RNG_IRQn); + g_ble_rng_isr_cb = cb; + } + + return 0; +} + +/** + * Start the random number generator + * + * @return int + */ +int +ble_hw_rng_start(void) +{ + os_sr_t sr; + + /* No need for interrupt if there is no callback */ + OS_ENTER_CRITICAL(sr); + NRF_RNG->EVENTS_VALRDY = 0; + if (g_ble_rng_isr_cb) { + NRF_RNG->INTENSET = 1; + } + NRF_RNG->TASKS_START = 1; + OS_EXIT_CRITICAL(sr); + + return 0; +} + +/** + * Stop the random generator + * + * @return int + */ +int +ble_hw_rng_stop(void) +{ + os_sr_t sr; + + /* No need for interrupt if there is no callback */ + OS_ENTER_CRITICAL(sr); + NRF_RNG->INTENCLR = 1; + NRF_RNG->TASKS_STOP = 1; + NRF_RNG->EVENTS_VALRDY = 0; + OS_EXIT_CRITICAL(sr); + + return 0; +} + +/** + * Read the random number generator. + * + * @return uint8_t + */ +uint8_t +ble_hw_rng_read(void) +{ + uint8_t rnum; + + /* Wait for a sample */ + while (NRF_RNG->EVENTS_VALRDY == 0) { + } + + NRF_RNG->EVENTS_VALRDY = 0; + rnum = (uint8_t)NRF_RNG->VALUE; + + return rnum; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) +/** + * Clear the resolving list + * + * @return int + */ +void +ble_hw_resolv_list_clear(void) +{ + g_nrf_num_irks = 0; +} + +/** + * Add a device to the hw resolving list + * + * @param irk Pointer to IRK to add + * + * @return int 0: success, BLE error code otherwise + */ +int +ble_hw_resolv_list_add(uint8_t *irk) +{ + uint32_t *nrf_entry; + + /* Find first ununsed device address match element */ + if (g_nrf_num_irks == NRF_IRK_LIST_ENTRIES) { + return BLE_ERR_MEM_CAPACITY; + } + + /* Copy into irk list */ + nrf_entry = &g_nrf_irk_list[4 * g_nrf_num_irks]; + memcpy(nrf_entry, irk, 16); + + /* Add to total */ + ++g_nrf_num_irks; + return BLE_ERR_SUCCESS; +} + +/** + * Remove a device from the hw resolving list + * + * @param index Index of IRK to remove + */ +void +ble_hw_resolv_list_rmv(int index) +{ + uint32_t *irk_entry; + + if (index < g_nrf_num_irks) { + --g_nrf_num_irks; + irk_entry = &g_nrf_irk_list[index]; + if (g_nrf_num_irks > index) { + memmove(irk_entry, irk_entry + 4, 16 * (g_nrf_num_irks - index)); + } + } +} + +/** + * Returns the size of the resolving list. NOTE: this returns the maximum + * allowable entries in the HW. Configuration options may limit this. + * + * @return int Number of devices allowed in resolving list + */ +uint8_t +ble_hw_resolv_list_size(void) +{ + return BLE_HW_RESOLV_LIST_SIZE; +} + +/** + * Called to determine if the address received was resolved. + * + * @return int Negative values indicate unresolved address; positive values + * indicate index in resolving list of resolved address. + */ +int +ble_hw_resolv_list_match(void) +{ + uint32_t index; + + if (NRF_AAR->EVENTS_END) { + if (NRF_AAR->EVENTS_RESOLVED) { + index = NRF_AAR->STATUS; + return (int)index; + } + } + + return -1; +} +#endif +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_phy.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_phy.c new file mode 100644 index 000000000..2ee29ab9c --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_phy.c @@ -0,0 +1,2120 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + #if defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) + +#include +#include +#include +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "../include/ble/xcvr.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/include/nimble/nimble_opt.h" +#include "nimble/nimble/include/nimble/nimble_npl.h" +#include "nimble/nimble/controller/include/controller/ble_phy.h" +#include "nimble/nimble/controller/include/controller/ble_phy_trace.h" +#include "nimble/nimble/controller/include/controller/ble_ll.h" +#include "nrf.h" +#if MYNEWT +#include "mcu/nrf52_clock.h" +#include "mcu/cmsis_nvic.h" +#include "hal/hal_gpio.h" +#else +#include "core_cm4.h" +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) +#if !MYNEWT_VAL_CHOICE(MCU_TARGET, nRF52840) && !MYNEWT_VAL_CHOICE(MCU_TARGET, nRF52811) +#error LE Coded PHY can only be enabled on nRF52811 or nRF52840 +#endif +#endif + +/* + * NOTE: This code uses a couple of PPI channels so care should be taken when + * using PPI somewhere else. + * + * Pre-programmed channels: CH20, CH21, CH23, CH25, CH31 + * Regular channels: CH4, CH5 and optionally CH17, CH18, CH19 + * - CH4 = cancel wfr timer on address match + * - CH5 = disable radio on wfr timer expiry + * - CH17 = (optional) gpio debug for radio ramp-up + * - CH18 = (optional) gpio debug for wfr timer RX enabled + * - CH19 = (optional) gpio debug for wfr timer radio disabled + * + */ + +/* XXX: 4) Make sure RF is higher priority interrupt than schedule */ + +/* + * XXX: Maximum possible transmit time is 1 msec for a 60ppm crystal + * and 16ms for a 30ppm crystal! We need to limit PDU size based on + * crystal accuracy. Look at this in the spec. + */ + +/* XXX: private header file? */ +extern uint8_t g_nrf_num_irks; +extern uint32_t g_nrf_irk_list[]; + +/* To disable all radio interrupts */ +#define NRF_RADIO_IRQ_MASK_ALL (0x34FF) + +/* + * We configure the nrf with a 1 byte S0 field, 8 bit length field, and + * zero bit S1 field. The preamble is 8 bits long. + */ +#define NRF_LFLEN_BITS (8) +#define NRF_S0LEN (1) +#define NRF_S1LEN_BITS (0) +#define NRF_CILEN_BITS (2) +#define NRF_TERMLEN_BITS (3) + +/* Maximum length of frames */ +#define NRF_MAXLEN (255) +#define NRF_BALEN (3) /* For base address of 3 bytes */ + +/* NRF_RADIO->PCNF0 configuration values */ +#define NRF_PCNF0 (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos) | \ + (RADIO_PCNF0_S1INCL_Msk) | \ + (NRF_S0LEN << RADIO_PCNF0_S0LEN_Pos) | \ + (NRF_S1LEN_BITS << RADIO_PCNF0_S1LEN_Pos) +#define NRF_PCNF0_1M (NRF_PCNF0) | \ + (RADIO_PCNF0_PLEN_8bit << RADIO_PCNF0_PLEN_Pos) +#define NRF_PCNF0_2M (NRF_PCNF0) | \ + (RADIO_PCNF0_PLEN_16bit << RADIO_PCNF0_PLEN_Pos) +#define NRF_PCNF0_CODED (NRF_PCNF0) | \ + (RADIO_PCNF0_PLEN_LongRange << RADIO_PCNF0_PLEN_Pos) | \ + (NRF_CILEN_BITS << RADIO_PCNF0_CILEN_Pos) | \ + (NRF_TERMLEN_BITS << RADIO_PCNF0_TERMLEN_Pos) + +/* BLE PHY data structure */ +struct ble_phy_obj +{ + uint8_t phy_stats_initialized; + int8_t phy_txpwr_dbm; + uint8_t phy_chan; + uint8_t phy_state; + uint8_t phy_transition; + uint8_t phy_transition_late; + uint8_t phy_rx_started; + uint8_t phy_encrypted; + uint8_t phy_privacy; + uint8_t phy_tx_pyld_len; + uint8_t phy_cur_phy_mode; + uint8_t phy_tx_phy_mode; + uint8_t phy_rx_phy_mode; + uint8_t phy_bcc_offset; + int8_t rx_pwr_compensation; + uint32_t phy_aar_scratch; + uint32_t phy_access_address; + struct ble_mbuf_hdr rxhdr; + void *txend_arg; + ble_phy_tx_end_func txend_cb; + uint32_t phy_start_cputime; +}; +struct ble_phy_obj g_ble_phy_data; + +/* XXX: if 27 byte packets desired we can make this smaller */ +/* Global transmit/receive buffer */ +static uint32_t g_ble_phy_tx_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; +static uint32_t g_ble_phy_rx_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) +/* Make sure word-aligned for faster copies */ +static uint32_t g_ble_phy_enc_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; +#endif + +/* RF center frequency for each channel index (offset from 2400 MHz) */ +static const uint8_t g_ble_phy_chan_freq[BLE_PHY_NUM_CHANS] = { + 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, /* 0-9 */ + 24, 28, 30, 32, 34, 36, 38, 40, 42, 44, /* 10-19 */ + 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, /* 20-29 */ + 66, 68, 70, 72, 74, 76, 78, 2, 26, 80, /* 30-39 */ +}; + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +/* packet start offsets (in usecs) */ +static const uint16_t g_ble_phy_mode_pkt_start_off[BLE_PHY_NUM_MODE] = { + [BLE_PHY_MODE_1M] = 40, + [BLE_PHY_MODE_2M] = 24, + [BLE_PHY_MODE_CODED_125KBPS] = 376, + [BLE_PHY_MODE_CODED_500KBPS] = 376 +}; +#endif + +/* Various radio timings */ +/* Radio ramp-up times in usecs (fast mode) */ +#define BLE_PHY_T_TXENFAST (XCVR_TX_RADIO_RAMPUP_USECS) +#define BLE_PHY_T_RXENFAST (XCVR_RX_RADIO_RAMPUP_USECS) +/* delay between EVENTS_READY and start of tx */ +static const uint8_t g_ble_phy_t_txdelay[BLE_PHY_NUM_MODE] = { + [BLE_PHY_MODE_1M] = 4, + [BLE_PHY_MODE_2M] = 3, + [BLE_PHY_MODE_CODED_125KBPS] = 5, + [BLE_PHY_MODE_CODED_500KBPS] = 5 +}; +/* delay between EVENTS_END and end of txd packet */ +static const uint8_t g_ble_phy_t_txenddelay[BLE_PHY_NUM_MODE] = { + [BLE_PHY_MODE_1M] = 4, + [BLE_PHY_MODE_2M] = 3, + [BLE_PHY_MODE_CODED_125KBPS] = 9, + [BLE_PHY_MODE_CODED_500KBPS] = 3 +}; +/* delay between rxd access address (w/ TERM1 for coded) and EVENTS_ADDRESS */ +static const uint8_t g_ble_phy_t_rxaddrdelay[BLE_PHY_NUM_MODE] = { + [BLE_PHY_MODE_1M] = 6, + [BLE_PHY_MODE_2M] = 2, + [BLE_PHY_MODE_CODED_125KBPS] = 17, + [BLE_PHY_MODE_CODED_500KBPS] = 17 +}; +/* delay between end of rxd packet and EVENTS_END */ +static const uint8_t g_ble_phy_t_rxenddelay[BLE_PHY_NUM_MODE] = { + [BLE_PHY_MODE_1M] = 6, + [BLE_PHY_MODE_2M] = 2, + [BLE_PHY_MODE_CODED_125KBPS] = 27, + [BLE_PHY_MODE_CODED_500KBPS] = 22 +}; + +/* Statistics */ +STATS_SECT_START(ble_phy_stats) + STATS_SECT_ENTRY(phy_isrs) + STATS_SECT_ENTRY(tx_good) + STATS_SECT_ENTRY(tx_fail) + STATS_SECT_ENTRY(tx_late) + STATS_SECT_ENTRY(tx_bytes) + STATS_SECT_ENTRY(rx_starts) + STATS_SECT_ENTRY(rx_aborts) + STATS_SECT_ENTRY(rx_valid) + STATS_SECT_ENTRY(rx_crc_err) + STATS_SECT_ENTRY(rx_late) + STATS_SECT_ENTRY(radio_state_errs) + STATS_SECT_ENTRY(rx_hw_err) + STATS_SECT_ENTRY(tx_hw_err) +STATS_SECT_END +STATS_SECT_DECL(ble_phy_stats) ble_phy_stats; + +STATS_NAME_START(ble_phy_stats) + STATS_NAME(ble_phy_stats, phy_isrs) + STATS_NAME(ble_phy_stats, tx_good) + STATS_NAME(ble_phy_stats, tx_fail) + STATS_NAME(ble_phy_stats, tx_late) + STATS_NAME(ble_phy_stats, tx_bytes) + STATS_NAME(ble_phy_stats, rx_starts) + STATS_NAME(ble_phy_stats, rx_aborts) + STATS_NAME(ble_phy_stats, rx_valid) + STATS_NAME(ble_phy_stats, rx_crc_err) + STATS_NAME(ble_phy_stats, rx_late) + STATS_NAME(ble_phy_stats, radio_state_errs) + STATS_NAME(ble_phy_stats, rx_hw_err) + STATS_NAME(ble_phy_stats, tx_hw_err) +STATS_NAME_END(ble_phy_stats) + +/* + * NOTE: + * Tested the following to see what would happen: + * -> NVIC has radio irq enabled (interrupt # 1, mask 0x2). + * -> Set up nrf to receive. Clear ADDRESS event register. + * -> Enable ADDRESS interrupt on nrf5 by writing to INTENSET. + * -> Enable RX. + * -> Disable interrupts globally using OS_ENTER_CRITICAL(). + * -> Wait until a packet is received and the ADDRESS event occurs. + * -> Call ble_phy_disable(). + * + * At this point I wanted to see the state of the cortex NVIC. The IRQ + * pending bit was TRUE for the radio interrupt (as expected) as we never + * serviced the radio interrupt (interrupts were disabled). + * + * What was unexpected was this: without clearing the pending IRQ in the NVIC, + * when radio interrupts were re-enabled (address event bit in INTENSET set to + * 1) and the radio ADDRESS event register read 1 (it was never cleared after + * the first address event), the radio did not enter the ISR! I would have + * expected that if the following were true, an interrupt would occur: + * -> NVIC ISER bit set to TRUE + * -> NVIC ISPR bit reads TRUE, meaning interrupt is pending. + * -> Radio peripheral interrupts are enabled for some event (or events). + * -> Corresponding event register(s) in radio peripheral read 1. + * + * Not sure what the end result of all this is. We will clear the pending + * bit in the NVIC just to be sure when we disable the PHY. + */ + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + +/* + * Per nordic, the number of bytes needed for scratch is 16 + MAX_PKT_SIZE. + * However, when I used a smaller size it still overwrote the scratchpad. Until + * I figure this out I am just going to allocate 67 words so we have enough + * space for 267 bytes of scratch. I used 268 bytes since not sure if this + * needs to be aligned and burning a byte is no big deal. + */ +//#define NRF_ENC_SCRATCH_WORDS (((MYNEWT_VAL(BLE_LL_MAX_PKT_SIZE) + 16) + 3) / 4) +#define NRF_ENC_SCRATCH_WORDS (67) + +uint32_t g_nrf_encrypt_scratchpad[NRF_ENC_SCRATCH_WORDS]; + +struct nrf_ccm_data +{ + uint8_t key[16]; + uint64_t pkt_counter; + uint8_t dir_bit; + uint8_t iv[8]; +} __attribute__((packed)); + +struct nrf_ccm_data g_nrf_ccm_data; +#endif + +static void +ble_phy_apply_errata_102_106_107(void) +{ + /* [102] RADIO: PAYLOAD/END events delayed or not triggered after ADDRESS + * [106] RADIO: Higher CRC error rates for some access addresses + * [107] RADIO: Immediate address match for access addresses containing MSBs 0x00 + */ + *(volatile uint32_t *)0x40001774 = ((*(volatile uint32_t *)0x40001774) & + 0xfffffffe) | 0x01000000; +} + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + +/* Packet start offset (in usecs). This is the preamble plus access address. + * For LE Coded PHY this also includes CI and TERM1. */ +uint32_t +ble_phy_mode_pdu_start_off(int phy_mode) +{ + return g_ble_phy_mode_pkt_start_off[phy_mode]; +} + +#if NRF52840_XXAA +static inline bool +ble_phy_mode_is_coded(uint8_t phy_mode) +{ + return (phy_mode == BLE_PHY_MODE_CODED_125KBPS) || + (phy_mode == BLE_PHY_MODE_CODED_500KBPS); +} + +static void +ble_phy_apply_nrf52840_errata(uint8_t new_phy_mode) +{ + bool new_coded = ble_phy_mode_is_coded(new_phy_mode); + bool cur_coded = ble_phy_mode_is_coded(g_ble_phy_data.phy_cur_phy_mode); + + /* + * Workarounds should be applied only when switching to/from LE Coded PHY + * so no need to apply them every time. + * + * nRF52840 Engineering A Errata v1.2 + * [164] RADIO: Low sensitivity in long range mode + * + * nRF52840 Rev 1 Errata + * [191] RADIO: High packet error rate in BLE Long Range mode + */ + if (new_coded == cur_coded) { + return; + } + + if (new_coded) { +#if MYNEWT_VAL(BLE_PHY_NRF52840_ERRATA_164) + /* [164] */ + *(volatile uint32_t *)0x4000173C |= 0x80000000; + *(volatile uint32_t *)0x4000173C = + ((*(volatile uint32_t *)0x4000173C & 0xFFFFFF00) | 0x5C); +#endif +#if MYNEWT_VAL(BLE_PHY_NRF52840_ERRATA_191) + /* [191] */ + *(volatile uint32_t *) 0x40001740 = + ((*((volatile uint32_t *) 0x40001740)) & 0x7FFF00FF) | + 0x80000000 | (((uint32_t)(196)) << 8); +#endif + } else { +#if MYNEWT_VAL(BLE_PHY_NRF52840_ERRATA_164) + /* [164] */ + *(volatile uint32_t *)0x4000173C &= ~0x80000000; +#endif +#if MYNEWT_VAL(BLE_PHY_NRF52840_ERRATA_191) + /* [191] */ + *(volatile uint32_t *) 0x40001740 = + ((*((volatile uint32_t *) 0x40001740)) & 0x7FFFFFFF); +#endif + } +} +#endif + +static void +ble_phy_mode_apply(uint8_t phy_mode) +{ + if (phy_mode == g_ble_phy_data.phy_cur_phy_mode) { + return; + } + +#if NRF52840_XXAA + ble_phy_apply_nrf52840_errata(phy_mode); +#endif + + switch (phy_mode) { + case BLE_PHY_MODE_1M: + NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_1Mbit; + NRF_RADIO->PCNF0 = NRF_PCNF0_1M; + break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) + case BLE_PHY_MODE_2M: + NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_2Mbit; + NRF_RADIO->PCNF0 = NRF_PCNF0_2M; + break; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + case BLE_PHY_MODE_CODED_125KBPS: + NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_LR125Kbit; + NRF_RADIO->PCNF0 = NRF_PCNF0_CODED; + break; + case BLE_PHY_MODE_CODED_500KBPS: + NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_LR500Kbit; + NRF_RADIO->PCNF0 = NRF_PCNF0_CODED; + break; +#endif + default: + assert(0); + } + + g_ble_phy_data.phy_cur_phy_mode = phy_mode; +} + +void +ble_phy_mode_set(uint8_t tx_phy_mode, uint8_t rx_phy_mode) +{ + g_ble_phy_data.phy_tx_phy_mode = tx_phy_mode; + g_ble_phy_data.phy_rx_phy_mode = rx_phy_mode; +} +#endif + +int +ble_phy_get_cur_phy(void) +{ +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + switch (g_ble_phy_data.phy_cur_phy_mode) { + case BLE_PHY_MODE_1M: + return BLE_PHY_1M; + case BLE_PHY_MODE_2M: + return BLE_PHY_2M; + case BLE_PHY_MODE_CODED_125KBPS: + case BLE_PHY_MODE_CODED_500KBPS: + return BLE_PHY_CODED; + default: + assert(0); + return -1; + } +#else + return BLE_PHY_1M; +#endif +} + +/** + * Copies the data from the phy receive buffer into a mbuf chain. + * + * @param dptr Pointer to receive buffer + * @param rxpdu Pointer to already allocated mbuf chain + * + * NOTE: the packet header already has the total mbuf length in it. The + * lengths of the individual mbufs are not set prior to calling. + * + */ +void +ble_phy_rxpdu_copy(uint8_t *dptr, struct os_mbuf *rxpdu) +{ + uint32_t rem_len; + uint32_t copy_len; + uint32_t block_len; + uint32_t block_rem_len; + void *dst; + void *src; + struct os_mbuf * om; + + /* Better be aligned */ + assert(((uint32_t)dptr & 3) == 0); + + block_len = rxpdu->om_omp->omp_databuf_len; + rem_len = OS_MBUF_PKTHDR(rxpdu)->omp_len; + src = dptr; + + /* + * Setup for copying from first mbuf which is shorter due to packet header + * and extra leading space + */ + copy_len = block_len - rxpdu->om_pkthdr_len - 4; + om = rxpdu; + dst = om->om_data; + + while (true) { + /* + * Always copy blocks of length aligned to word size, only last mbuf + * will have remaining non-word size bytes appended. + */ + block_rem_len = copy_len; + copy_len = min(copy_len, rem_len); + copy_len &= ~3; + + dst = om->om_data; + om->om_len = copy_len; + rem_len -= copy_len; + block_rem_len -= copy_len; + + __asm__ volatile (".syntax unified \n" + " mov r4, %[len] \n" + " b 2f \n" + "1: ldr r3, [%[src], %[len]] \n" + " str r3, [%[dst], %[len]] \n" + "2: subs %[len], #4 \n" + " bpl 1b \n" + " adds %[src], %[src], r4 \n" + " adds %[dst], %[dst], r4 \n" + : [dst] "+r" (dst), [src] "+r" (src), + [len] "+r" (copy_len) + : + : "r3", "r4", "memory" + ); + + if ((rem_len < 4) && (block_rem_len >= rem_len)) { + break; + } + + /* Move to next mbuf */ + om = SLIST_NEXT(om, om_next); + copy_len = block_len; + } + + /* Copy remaining bytes, if any, to last mbuf */ + om->om_len += rem_len; + __asm__ volatile (".syntax unified \n" + " b 2f \n" + "1: ldrb r3, [%[src], %[len]] \n" + " strb r3, [%[dst], %[len]] \n" + "2: subs %[len], #1 \n" + " bpl 1b \n" + : [len] "+r" (rem_len) + : [dst] "r" (dst), [src] "r" (src) + : "r3", "memory" + ); + + /* Copy header */ + memcpy(BLE_MBUF_HDR_PTR(rxpdu), &g_ble_phy_data.rxhdr, + sizeof(struct ble_mbuf_hdr)); +} + +/** + * Called when we want to wait if the radio is in either the rx or tx + * disable states. We want to wait until that state is over before doing + * anything to the radio + */ +static void +nrf_wait_disabled(void) +{ + uint32_t state; + + state = NRF_RADIO->STATE; + if (state != RADIO_STATE_STATE_Disabled) { + if ((state == RADIO_STATE_STATE_RxDisable) || + (state == RADIO_STATE_STATE_TxDisable)) { + /* This will end within a short time (6 usecs). Just poll */ + while (NRF_RADIO->STATE == state) { + /* If this fails, something is really wrong. Should last + * no more than 6 usecs */ + } + } + } +} + +/** + * + * + */ +static int +ble_phy_set_start_time(uint32_t cputime, uint8_t rem_usecs, bool tx) +{ + uint32_t next_cc; + uint32_t cur_cc; + uint32_t cntr; + uint32_t delta; + + /* + * We need to adjust start time to include radio ramp-up and TX pipeline + * delay (the latter only if applicable, so only for TX). + * + * Radio ramp-up time is 40 usecs and TX delay is 3 or 5 usecs depending on + * phy, thus we'll offset RTC by 2 full ticks (61 usecs) and then compensate + * using TIMER0 with 1 usec precision. + */ + + cputime -= 2; + rem_usecs += 61; + if (tx) { + rem_usecs -= BLE_PHY_T_TXENFAST; + rem_usecs -= g_ble_phy_t_txdelay[g_ble_phy_data.phy_cur_phy_mode]; + } else { + rem_usecs -= BLE_PHY_T_RXENFAST; + } + + /* + * rem_usecs will be no more than 2 ticks, but if it is more than single + * tick then we should better count one more low-power tick rather than + * 30 high-power usecs. Also make sure we don't set TIMER0 CC to 0 as the + * compare won't occur. + */ + + if (rem_usecs > 30) { + cputime++; + rem_usecs -= 30; + } + + /* + * Can we set the RTC compare to start TIMER0? We can do it if: + * a) Current compare value is not N+1 or N+2 ticks from current + * counter. + * b) The value we want to set is not at least N+2 from current + * counter. + * + * NOTE: since the counter can tick 1 while we do these calculations we + * need to account for it. + */ + next_cc = cputime & 0xffffff; + cur_cc = NRF_RTC0->CC[0]; + cntr = NRF_RTC0->COUNTER; + + delta = (cur_cc - cntr) & 0xffffff; + if ((delta <= 3) && (delta != 0)) { + return -1; + } + delta = (next_cc - cntr) & 0xffffff; + if ((delta & 0x800000) || (delta < 3)) { + return -1; + } + + /* Clear and set TIMER0 to fire off at proper time */ + NRF_TIMER0->TASKS_CLEAR = 1; + NRF_TIMER0->CC[0] = rem_usecs; + NRF_TIMER0->EVENTS_COMPARE[0] = 0; + + /* Set RTC compare to start TIMER0 */ + NRF_RTC0->EVENTS_COMPARE[0] = 0; + NRF_RTC0->CC[0] = next_cc; + NRF_RTC0->EVTENSET = RTC_EVTENSET_COMPARE0_Msk; + + /* Enable PPI */ + NRF_PPI->CHENSET = PPI_CHEN_CH31_Msk; + + /* Store the cputime at which we set the RTC */ + g_ble_phy_data.phy_start_cputime = cputime; + + return 0; +} + +static int +ble_phy_set_start_now(void) +{ + os_sr_t sr; + uint32_t now; + + OS_ENTER_CRITICAL(sr); + + /* + * Set TIMER0 to fire immediately. We can't set CC to 0 as compare will not + * occur in such case. + */ + NRF_TIMER0->TASKS_CLEAR = 1; + NRF_TIMER0->CC[0] = 1; + NRF_TIMER0->EVENTS_COMPARE[0] = 0; + + /* + * Set RTC compare to start TIMER0. We need to set it to at least N+2 ticks + * from current value to guarantee triggering compare event, but let's set + * it to N+3 to account for possible extra tick on RTC0 during these + * operations. + */ + now = os_cputime_get32(); + NRF_RTC0->EVENTS_COMPARE[0] = 0; + NRF_RTC0->CC[0] = now + 3; + NRF_RTC0->EVTENSET = RTC_EVTENSET_COMPARE0_Msk; + + /* Enable PPI */ + NRF_PPI->CHENSET = PPI_CHEN_CH31_Msk; + + /* + * Store the cputime at which we set the RTC + * + * XXX Compare event may be triggered on previous CC value (if it was set to + * less than N+2) so in rare cases actual start time may be 2 ticks earlier + * than what we expect. Since this is only used on RX, it may cause AUX scan + * to be scheduled 1 or 2 ticks too late so we'll miss it - it's acceptable + * for now. + */ + g_ble_phy_data.phy_start_cputime = now + 3; + + OS_EXIT_CRITICAL(sr); + + return 0; +} + +/** + * Function is used to set PPI so that we can time out waiting for a reception + * to occur. This happens for two reasons: we have sent a packet and we are + * waiting for a respons (txrx should be set to ENABLE_TXRX) or we are + * starting a connection event and we are a slave and we are waiting for the + * master to send us a packet (txrx should be set to ENABLE_RX). + * + * NOTE: when waiting for a txrx turn-around, wfr_usecs is not used as there + * is no additional time to wait; we know when we should receive the address of + * the received frame. + * + * @param txrx Flag denoting if this wfr is a txrx turn-around or not. + * @param tx_phy_mode phy mode for last TX (only valid for TX->RX) + * @param wfr_usecs Amount of usecs to wait. + */ +void +ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs) +{ + uint32_t end_time; + uint8_t phy; + + phy = g_ble_phy_data.phy_cur_phy_mode; + + if (txrx == BLE_PHY_WFR_ENABLE_TXRX) { + /* RX shall start exactly T_IFS after TX end captured in CC[2] */ + end_time = NRF_TIMER0->CC[2] + BLE_LL_IFS; + /* Adjust for delay between EVENT_END and actual TX end time */ + end_time += g_ble_phy_t_txenddelay[tx_phy_mode]; + /* Wait a bit longer due to allowed active clock accuracy */ + end_time += 2; + /* + * It's possible that we'll capture PDU start time at the end of timer + * cycle and since wfr expires at the beginning of calculated timer + * cycle it can be almost 1 usec too early. Let's compensate for this + * by waiting 1 usec more. + */ + end_time += 1; +#if MYNEWT_VAL(BLE_PHY_CODED_RX_IFS_EXTRA_MARGIN) > 0 + if ((phy == BLE_PHY_MODE_CODED_125KBPS) || + (phy == BLE_PHY_MODE_CODED_500KBPS)) { + /* + * Some controllers exceed T_IFS when transmitting on coded phy + * so let's wait a bit longer to be able to talk to them if this + * workaround is enabled. + */ + end_time += MYNEWT_VAL(BLE_PHY_CODED_RX_IFS_EXTRA_MARGIN); + } +#endif + } else { + /* + * RX shall start no later than wfr_usecs after RX enabled. + * CC[0] is the time of RXEN so adjust for radio ram-up. + * Do not add jitter since this is already covered by LL. + */ + end_time = NRF_TIMER0->CC[0] + BLE_PHY_T_RXENFAST + wfr_usecs; + } + + /* + * Note: on LE Coded EVENT_ADDRESS is fired after TERM1 is received, so + * we are actually calculating relative to start of packet payload + * which is fine. + */ + + /* Adjust for receiving access address since this triggers EVENT_ADDRESS */ + end_time += ble_phy_mode_pdu_start_off(phy); + /* Adjust for delay between actual access address RX and EVENT_ADDRESS */ + end_time += g_ble_phy_t_rxaddrdelay[phy]; + + /* wfr_secs is the time from rxen until timeout */ + NRF_TIMER0->CC[3] = end_time; + NRF_TIMER0->EVENTS_COMPARE[3] = 0; + + /* Enable wait for response PPI */ + NRF_PPI->CHENSET = (PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk); + + /* Enable the disabled interrupt so we time out on events compare */ + NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk; + + /* + * It may happen that if CPU is halted for a brief moment (e.g. during flash + * erase or write), TIMER0 already counted past CC[3] and thus wfr will not + * fire as expected. In case this happened, let's just disable PPIs for wfr + * and trigger wfr manually (i.e. disable radio). + * + * Note that the same applies to RX start time set in CC[0] but since it + * should fire earlier than wfr, fixing wfr is enough. + * + * CC[1] is only used as a reference on RX start, we do not need it here so + * it can be used to read TIMER0 counter. + */ + NRF_TIMER0->TASKS_CAPTURE[1] = 1; + if (NRF_TIMER0->CC[1] > NRF_TIMER0->CC[3]) { + NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk; + NRF_RADIO->TASKS_DISABLE = 1; + } +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) +static uint32_t +ble_phy_get_ccm_datarate(void) +{ +#if BLE_LL_BT5_PHY_SUPPORTED + switch (g_ble_phy_data.phy_cur_phy_mode) { + case BLE_PHY_MODE_1M: + return CCM_MODE_DATARATE_1Mbit << CCM_MODE_DATARATE_Pos; + case BLE_PHY_MODE_2M: + return CCM_MODE_DATARATE_2Mbit << CCM_MODE_DATARATE_Pos; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + case BLE_PHY_MODE_CODED_125KBPS: + return CCM_MODE_DATARATE_125Kbps << CCM_MODE_DATARATE_Pos; + case BLE_PHY_MODE_CODED_500KBPS: + return CCM_MODE_DATARATE_500Kbps << CCM_MODE_DATARATE_Pos; +#endif + } + + assert(0); + return 0; +#else + return CCM_MODE_DATARATE_1Mbit << CCM_MODE_DATARATE_Pos; +#endif +} +#endif + +/** + * Setup transceiver for receive. + */ +static void +ble_phy_rx_xcvr_setup(void) +{ + uint8_t *dptr; + + dptr = (uint8_t *)&g_ble_phy_rx_buf[0]; + dptr += 3; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + if (g_ble_phy_data.phy_encrypted) { + NRF_RADIO->PACKETPTR = (uint32_t)&g_ble_phy_enc_buf[0]; + NRF_CCM->INPTR = (uint32_t)&g_ble_phy_enc_buf[0]; + NRF_CCM->OUTPTR = (uint32_t)dptr; + NRF_CCM->SCRATCHPTR = (uint32_t)&g_nrf_encrypt_scratchpad[0]; + NRF_CCM->MODE = CCM_MODE_LENGTH_Msk | CCM_MODE_MODE_Decryption | + ble_phy_get_ccm_datarate(); + NRF_CCM->CNFPTR = (uint32_t)&g_nrf_ccm_data; + NRF_CCM->SHORTS = 0; + NRF_CCM->EVENTS_ERROR = 0; + NRF_CCM->EVENTS_ENDCRYPT = 0; + NRF_CCM->TASKS_KSGEN = 1; + NRF_PPI->CHENSET = PPI_CHEN_CH25_Msk; + } else { + NRF_RADIO->PACKETPTR = (uint32_t)dptr; + } +#else + NRF_RADIO->PACKETPTR = (uint32_t)dptr; +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + if (g_ble_phy_data.phy_privacy) { + NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Enabled; + NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0]; + NRF_AAR->SCRATCHPTR = (uint32_t)&g_ble_phy_data.phy_aar_scratch; + NRF_AAR->EVENTS_END = 0; + NRF_AAR->EVENTS_RESOLVED = 0; + NRF_AAR->EVENTS_NOTRESOLVED = 0; + } else { + if (g_ble_phy_data.phy_encrypted == 0) { + NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Disabled; + } + } +#endif + + /* Turn off trigger TXEN on output compare match and AAR on bcmatch */ + NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk | PPI_CHEN_CH23_Msk; + + /* Reset the rx started flag. Used for the wait for response */ + g_ble_phy_data.phy_rx_started = 0; + g_ble_phy_data.phy_state = BLE_PHY_STATE_RX; + +#if BLE_LL_BT5_PHY_SUPPORTED + /* + * On Coded PHY there are CI and TERM1 fields before PDU starts so we need + * to take this into account when setting up BCC. + */ + if (g_ble_phy_data.phy_cur_phy_mode == BLE_PHY_MODE_CODED_125KBPS || + g_ble_phy_data.phy_cur_phy_mode == BLE_PHY_MODE_CODED_500KBPS) { + g_ble_phy_data.phy_bcc_offset = 5; + } else { + g_ble_phy_data.phy_bcc_offset = 0; + } +#else + g_ble_phy_data.phy_bcc_offset = 0; +#endif + + /* I want to know when 1st byte received (after address) */ + NRF_RADIO->BCC = 8 + g_ble_phy_data.phy_bcc_offset; /* in bits */ + NRF_RADIO->EVENTS_ADDRESS = 0; + NRF_RADIO->EVENTS_DEVMATCH = 0; + NRF_RADIO->EVENTS_BCMATCH = 0; + NRF_RADIO->EVENTS_RSSIEND = 0; + NRF_RADIO->EVENTS_CRCOK = 0; + NRF_RADIO->SHORTS = RADIO_SHORTS_END_DISABLE_Msk | + RADIO_SHORTS_READY_START_Msk | + RADIO_SHORTS_ADDRESS_BCSTART_Msk | + RADIO_SHORTS_ADDRESS_RSSISTART_Msk | + RADIO_SHORTS_DISABLED_RSSISTOP_Msk; + + NRF_RADIO->INTENSET = RADIO_INTENSET_ADDRESS_Msk; +} + +/** + * Called from interrupt context when the transmit ends + * + */ +static void +ble_phy_tx_end_isr(void) +{ + uint8_t tx_phy_mode; + uint8_t was_encrypted; + uint8_t transition; + uint32_t rx_time; + uint32_t wfr_time; + + /* Store PHY on which we've just transmitted smth */ + tx_phy_mode = g_ble_phy_data.phy_cur_phy_mode; + + /* If this transmission was encrypted we need to remember it */ + was_encrypted = g_ble_phy_data.phy_encrypted; + (void)was_encrypted; + + /* Better be in TX state! */ + assert(g_ble_phy_data.phy_state == BLE_PHY_STATE_TX); + + /* Clear events and clear interrupt on disabled event */ + NRF_RADIO->EVENTS_DISABLED = 0; + NRF_RADIO->INTENCLR = RADIO_INTENCLR_DISABLED_Msk; + NRF_RADIO->EVENTS_END = 0; + wfr_time = NRF_RADIO->SHORTS; + (void)wfr_time; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + /* + * XXX: not sure what to do. We had a HW error during transmission. + * For now I just count a stat but continue on like all is good. + */ + if (was_encrypted) { + if (NRF_CCM->EVENTS_ERROR) { + STATS_INC(ble_phy_stats, tx_hw_err); + NRF_CCM->EVENTS_ERROR = 0; + } + } +#endif + + /* Call transmit end callback */ + if (g_ble_phy_data.txend_cb) { + g_ble_phy_data.txend_cb(g_ble_phy_data.txend_arg); + } + + transition = g_ble_phy_data.phy_transition; + if (transition == BLE_PHY_TRANSITION_TX_RX) { + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + ble_phy_mode_apply(g_ble_phy_data.phy_rx_phy_mode); +#endif + + /* Packet pointer needs to be reset. */ + ble_phy_rx_xcvr_setup(); + + ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_TXRX, tx_phy_mode, 0); + + /* Schedule RX exactly T_IFS after TX end captured in CC[2] */ + rx_time = NRF_TIMER0->CC[2] + BLE_LL_IFS; + /* Adjust for delay between EVENT_END and actual TX end time */ + rx_time += g_ble_phy_t_txenddelay[tx_phy_mode]; + /* Adjust for radio ramp-up */ + rx_time -= BLE_PHY_T_RXENFAST; + /* Start listening a bit earlier due to allowed active clock accuracy */ + rx_time -= 2; + + NRF_TIMER0->CC[0] = rx_time; + NRF_TIMER0->EVENTS_COMPARE[0] = 0; + NRF_PPI->CHENSET = PPI_CHEN_CH21_Msk; + } else { + /* + * XXX: not sure we need to stop the timer here all the time. Or that + * it should be stopped here. + */ + NRF_TIMER0->TASKS_STOP = 1; + NRF_TIMER0->TASKS_SHUTDOWN = 1; + NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | + PPI_CHEN_CH20_Msk | PPI_CHEN_CH31_Msk; + assert(transition == BLE_PHY_TRANSITION_NONE); + } +} + +static inline uint8_t +ble_phy_get_cur_rx_phy_mode(void) +{ + uint8_t phy; + + phy = g_ble_phy_data.phy_cur_phy_mode; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + /* + * For Coded PHY mode can be set to either codings since actual coding is + * set in packet header. However, here we need actual coding of received + * packet as this determines pipeline delays so need to figure this out + * using CI field. + */ + if ((phy == BLE_PHY_MODE_CODED_125KBPS) || + (phy == BLE_PHY_MODE_CODED_500KBPS)) { + phy = NRF_RADIO->PDUSTAT & RADIO_PDUSTAT_CISTAT_Msk ? + BLE_PHY_MODE_CODED_500KBPS : + BLE_PHY_MODE_CODED_125KBPS; + } +#endif + + return phy; +} + +static void +ble_phy_rx_end_isr(void) +{ + int rc; + uint8_t *dptr; + uint8_t crcok; + uint32_t tx_time; + struct ble_mbuf_hdr *ble_hdr; + + /* Clear events and clear interrupt */ + NRF_RADIO->EVENTS_END = 0; + NRF_RADIO->INTENCLR = RADIO_INTENCLR_END_Msk; + + /* Disable automatic RXEN */ + NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk; + + /* Set RSSI and CRC status flag in header */ + ble_hdr = &g_ble_phy_data.rxhdr; + assert(NRF_RADIO->EVENTS_RSSIEND != 0); + ble_hdr->rxinfo.rssi = (-1 * NRF_RADIO->RSSISAMPLE) + + g_ble_phy_data.rx_pwr_compensation; + + dptr = (uint8_t *)&g_ble_phy_rx_buf[0]; + dptr += 3; + + /* Count PHY crc errors and valid packets */ + crcok = NRF_RADIO->EVENTS_CRCOK; + if (!crcok) { + STATS_INC(ble_phy_stats, rx_crc_err); + } else { + STATS_INC(ble_phy_stats, rx_valid); + ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_CRC_OK; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + if (g_ble_phy_data.phy_encrypted) { + /* Only set MIC failure flag if frame is not zero length */ + if ((dptr[1] != 0) && (NRF_CCM->MICSTATUS == 0)) { + ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_MIC_FAILURE; + } + + /* + * XXX: not sure how to deal with this. This should not + * be a MIC failure but we should not hand it up. I guess + * this is just some form of rx error and that is how we + * handle it? For now, just set CRC error flags + */ + if (NRF_CCM->EVENTS_ERROR) { + STATS_INC(ble_phy_stats, rx_hw_err); + ble_hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_CRC_OK; + } + + /* + * XXX: This is a total hack work-around for now but I dont + * know what else to do. If ENDCRYPT is not set and we are + * encrypted we need to not trust this frame and drop it. + */ + if (NRF_CCM->EVENTS_ENDCRYPT == 0) { + STATS_INC(ble_phy_stats, rx_hw_err); + ble_hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_CRC_OK; + } + } +#endif + } + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + ble_phy_mode_apply(g_ble_phy_data.phy_tx_phy_mode); +#endif + + /* + * Let's schedule TX now and we will just cancel it after processing RXed + * packet if we don't need TX. + * + * We need this to initiate connection in case AUX_CONNECT_REQ was sent on + * LE Coded S8. In this case the time we process RXed packet is roughly the + * same as the limit when we need to have TX scheduled (i.e. TIMER0 and PPI + * armed) so we may simply miss the slot and set the timer in the past. + * + * When TX is scheduled in advance, we may event process packet a bit longer + * during radio ramp-up - this gives us extra 40 usecs which is more than + * enough. + */ + + /* Schedule TX exactly T_IFS after RX end captured in CC[2] */ + tx_time = NRF_TIMER0->CC[2] + BLE_LL_IFS; + /* Adjust for delay between actual RX end time and EVENT_END */ + tx_time -= g_ble_phy_t_rxenddelay[ble_hdr->rxinfo.phy_mode]; + /* Adjust for radio ramp-up */ + tx_time -= BLE_PHY_T_TXENFAST; + /* Adjust for delay between EVENT_READY and actual TX start time */ + tx_time -= g_ble_phy_t_txdelay[g_ble_phy_data.phy_cur_phy_mode]; + + NRF_TIMER0->CC[0] = tx_time; + NRF_TIMER0->EVENTS_COMPARE[0] = 0; + NRF_PPI->CHENSET = PPI_CHEN_CH20_Msk; + + /* + * XXX: Hack warning! + * + * It may happen (during flash erase) that CPU is stopped for a moment and + * TIMER0 already counted past CC[0]. In such case we will be stuck waiting + * for TX to start since EVENTS_COMPARE[0] will not happen any time soon. + * For now let's set a flag denoting that we are late in RX-TX transition so + * ble_phy_tx() will fail - this allows everything to cleanup nicely without + * the need for extra handling in many places. + * + * Note: CC[3] is used only for wfr which we do not need here. + */ + NRF_TIMER0->TASKS_CAPTURE[3] = 1; + if (NRF_TIMER0->CC[3] > NRF_TIMER0->CC[0]) { + NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk; + g_ble_phy_data.phy_transition_late = 1; + } + + /* + * XXX: This is a horrible ugly hack to deal with the RAM S1 byte + * that is not sent over the air but is present here. Simply move the + * data pointer to deal with it. Fix this later. + */ + dptr[2] = dptr[1]; + dptr[1] = dptr[0]; + rc = ble_ll_rx_end(dptr + 1, ble_hdr); + if (rc < 0) { + ble_phy_disable(); + } +} + +static bool +ble_phy_rx_start_isr(void) +{ + int rc; + uint32_t state; + uint32_t usecs; + uint32_t pdu_usecs; + uint32_t ticks; + struct ble_mbuf_hdr *ble_hdr; + uint8_t *dptr; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + int adva_offset; +#endif + + dptr = (uint8_t *)&g_ble_phy_rx_buf[0]; + + /* Clear events and clear interrupt */ + NRF_RADIO->EVENTS_ADDRESS = 0; + + /* Clear wfr timer channels and DISABLED interrupt */ + NRF_RADIO->INTENCLR = RADIO_INTENCLR_DISABLED_Msk | RADIO_INTENCLR_ADDRESS_Msk; + NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk; + + /* Initialize the ble mbuf header */ + ble_hdr = &g_ble_phy_data.rxhdr; + ble_hdr->rxinfo.flags = ble_ll_state_get(); + ble_hdr->rxinfo.channel = g_ble_phy_data.phy_chan; + ble_hdr->rxinfo.handle = 0; + ble_hdr->rxinfo.phy = ble_phy_get_cur_phy(); + ble_hdr->rxinfo.phy_mode = ble_phy_get_cur_rx_phy_mode(); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + ble_hdr->rxinfo.user_data = NULL; +#endif + + /* + * Calculate accurate packets start time (with remainder) + * + * We may start receiving packet somewhere during preamble in which case + * it is possible that actual transmission started before TIMER0 was + * running - need to take this into account. + */ + ble_hdr->beg_cputime = g_ble_phy_data.phy_start_cputime; + + usecs = NRF_TIMER0->CC[1]; + pdu_usecs = ble_phy_mode_pdu_start_off(ble_hdr->rxinfo.phy_mode) + + g_ble_phy_t_rxaddrdelay[ble_hdr->rxinfo.phy_mode]; + if (usecs < pdu_usecs) { + g_ble_phy_data.phy_start_cputime--; + usecs += 30; + } + usecs -= pdu_usecs; + + ticks = os_cputime_usecs_to_ticks(usecs); + usecs -= os_cputime_ticks_to_usecs(ticks); + if (usecs == 31) { + usecs = 0; + ++ticks; + } + + ble_hdr->beg_cputime += ticks; + ble_hdr->rem_usecs = usecs; + + /* XXX: I wonder if we always have the 1st byte. If we need to wait for + * rx chain delay, it could be 18 usecs from address interrupt. The + nrf52 may be able to get here early. */ + /* Wait to get 1st byte of frame */ + while (1) { + state = NRF_RADIO->STATE; + if (NRF_RADIO->EVENTS_BCMATCH != 0) { + break; + } + + /* + * If state is disabled, we should have the BCMATCH. If not, + * something is wrong! + */ + if (state == RADIO_STATE_STATE_Disabled) { + NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL; + NRF_RADIO->SHORTS = 0; + return false; + } + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + /* + * If privacy is enabled and received PDU has TxAdd bit set (i.e. random + * address) we try to resolve address using AAR. + */ + if (g_ble_phy_data.phy_privacy && (dptr[3] & 0x40)) { + /* + * AdvA is located at 4th octet in RX buffer (after S0, length an S1 + * fields). In case of extended advertising PDU we need to add 2 more + * octets for extended header. + */ + adva_offset = (dptr[3] & 0x0f) == 0x07 ? 2 : 0; + NRF_AAR->ADDRPTR = (uint32_t)(dptr + 3 + adva_offset); + + /* Trigger AAR after last bit of AdvA is received */ + NRF_RADIO->EVENTS_BCMATCH = 0; + NRF_PPI->CHENSET = PPI_CHEN_CH23_Msk; + NRF_RADIO->BCC = (BLE_LL_PDU_HDR_LEN + adva_offset + BLE_DEV_ADDR_LEN) * 8 + + g_ble_phy_data.phy_bcc_offset; + } +#endif + + /* Call Link Layer receive start function */ + rc = ble_ll_rx_start(dptr + 3, + g_ble_phy_data.phy_chan, + &g_ble_phy_data.rxhdr); + if (rc >= 0) { + /* Set rx started flag and enable rx end ISR */ + g_ble_phy_data.phy_rx_started = 1; + NRF_RADIO->INTENSET = RADIO_INTENSET_END_Msk; + } else { + /* Disable PHY */ + ble_phy_disable(); + STATS_INC(ble_phy_stats, rx_aborts); + } + + /* Count rx starts */ + STATS_INC(ble_phy_stats, rx_starts); + + return true; +} + +static void +ble_phy_isr(void) +{ + uint32_t irq_en; + + os_trace_isr_enter(); + + /* Read irq register to determine which interrupts are enabled */ + irq_en = NRF_RADIO->INTENCLR; + + /* + * NOTE: order of checking is important! Possible, if things get delayed, + * we have both an ADDRESS and DISABLED interrupt in rx state. If we get + * an address, we disable the DISABLED interrupt. + */ + + /* We get this if we have started to receive a frame */ + if ((irq_en & RADIO_INTENCLR_ADDRESS_Msk) && NRF_RADIO->EVENTS_ADDRESS) { + /* + * wfr timer is calculated to expire at the exact time we should start + * receiving a packet (with 1 usec precision) so it is possible it will + * fire at the same time as EVENT_ADDRESS. If this happens, radio will + * be disabled while we are waiting for EVENT_BCCMATCH after 1st byte + * of payload is received and ble_phy_rx_start_isr() will fail. In this + * case we should not clear DISABLED irq mask so it will be handled as + * regular radio disabled event below. In other case radio was disabled + * on purpose and there's nothing more to handle so we can clear mask. + */ + if (ble_phy_rx_start_isr()) { + irq_en &= ~RADIO_INTENCLR_DISABLED_Msk; + } + } + + /* Check for disabled event. This only happens for transmits now */ + if ((irq_en & RADIO_INTENCLR_DISABLED_Msk) && NRF_RADIO->EVENTS_DISABLED) { + if (g_ble_phy_data.phy_state == BLE_PHY_STATE_RX) { + NRF_RADIO->EVENTS_DISABLED = 0; + ble_ll_wfr_timer_exp(NULL); + } else if (g_ble_phy_data.phy_state == BLE_PHY_STATE_IDLE) { + assert(0); + } else { + ble_phy_tx_end_isr(); + } + } + + /* Receive packet end (we dont enable this for transmit) */ + if ((irq_en & RADIO_INTENCLR_END_Msk) && NRF_RADIO->EVENTS_END) { + ble_phy_rx_end_isr(); + } + + g_ble_phy_data.phy_transition_late = 0; + + /* Ensures IRQ is cleared */ + irq_en = NRF_RADIO->SHORTS; + + /* Count # of interrupts */ + STATS_INC(ble_phy_stats, phy_isrs); + + os_trace_isr_exit(); +} + +#if MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0 || \ + MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0 || \ + MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0 +static inline void +ble_phy_dbg_time_setup_gpiote(int index, int pin) +{ + NRF_GPIO_Type *port; + +#if NRF52840_XXAA + port = pin > 31 ? NRF_P1 : NRF_P0; + pin &= 0x1f; +#else + port = NRF_P0; +#endif + + /* Configure GPIO directly to avoid dependency to hal_gpio (for porting) */ + port->DIRSET = (1 << pin); + port->OUTCLR = (1 << pin); + + NRF_GPIOTE->CONFIG[index] = + (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) | + ((pin & 0x1F) << GPIOTE_CONFIG_PSEL_Pos) | +#if NRF52840_XXAA + ((port == NRF_P1) << GPIOTE_CONFIG_PORT_Pos); +#else + 0; +#endif +} +#endif + +static void +ble_phy_dbg_time_setup(void) +{ + int gpiote_idx __attribute__((unused)) = 8; + + /* + * We setup GPIOTE starting from last configuration index to minimize risk + * of conflict with GPIO setup via hal. It's not great solution, but since + * this is just debugging code we can live with this. + */ + +#if MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0 + ble_phy_dbg_time_setup_gpiote(--gpiote_idx, + MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN)); + + NRF_PPI->CH[17].EEP = (uint32_t)&(NRF_RADIO->EVENTS_READY); + NRF_PPI->CH[17].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[gpiote_idx]); + NRF_PPI->CHENSET = PPI_CHEN_CH17_Msk; + + /* CH[20] and PPI CH[21] are on to trigger TASKS_TXEN or TASKS_RXEN */ + NRF_PPI->FORK[20].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[gpiote_idx]); + NRF_PPI->FORK[21].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[gpiote_idx]); +#endif + +#if MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0 + ble_phy_dbg_time_setup_gpiote(--gpiote_idx, + MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN)); + + /* CH[26] and CH[27] are always on for EVENT_ADDRESS and EVENT_END */ + NRF_PPI->FORK[26].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[gpiote_idx]); + NRF_PPI->FORK[27].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[gpiote_idx]); +#endif + +#if MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0 + ble_phy_dbg_time_setup_gpiote(--gpiote_idx, + MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN)); + +#if NRF52840_XXAA + NRF_PPI->CH[18].EEP = (uint32_t)&(NRF_RADIO->EVENTS_RXREADY); +#else + NRF_PPI->CH[18].EEP = (uint32_t)&(NRF_RADIO->EVENTS_READY); +#endif + NRF_PPI->CH[18].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[gpiote_idx]); + NRF_PPI->CH[19].EEP = (uint32_t)&(NRF_RADIO->EVENTS_DISABLED); + NRF_PPI->CH[19].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[gpiote_idx]); + NRF_PPI->CHENSET = PPI_CHEN_CH18_Msk | PPI_CHEN_CH19_Msk; + + /* CH[4] and CH[5] are always on for wfr */ + NRF_PPI->FORK[4].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[gpiote_idx]); + NRF_PPI->FORK[5].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[gpiote_idx]); +#endif +} + +/** + * ble phy init + * + * Initialize the PHY. + * + * @return int 0: success; PHY error code otherwise + */ +int +ble_phy_init(void) +{ + int rc; + + /* Default phy to use is 1M */ + g_ble_phy_data.phy_cur_phy_mode = BLE_PHY_MODE_1M; + g_ble_phy_data.phy_tx_phy_mode = BLE_PHY_MODE_1M; + g_ble_phy_data.phy_rx_phy_mode = BLE_PHY_MODE_1M; + + g_ble_phy_data.rx_pwr_compensation = 0; + + /* Set phy channel to an invalid channel so first set channel works */ + g_ble_phy_data.phy_chan = BLE_PHY_NUM_CHANS; + + /* Toggle peripheral power to reset (just in case) */ + NRF_RADIO->POWER = 0; + NRF_RADIO->POWER = 1; + + /* Disable all interrupts */ + NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL; + + /* Set configuration registers */ + NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_1Mbit; + NRF_RADIO->PCNF0 = NRF_PCNF0; + + /* XXX: should maxlen be 251 for encryption? */ + NRF_RADIO->PCNF1 = NRF_MAXLEN | + (RADIO_PCNF1_ENDIAN_Little << RADIO_PCNF1_ENDIAN_Pos) | + (NRF_BALEN << RADIO_PCNF1_BALEN_Pos) | + RADIO_PCNF1_WHITEEN_Msk; + + /* Enable radio fast ramp-up */ + NRF_RADIO->MODECNF0 |= (RADIO_MODECNF0_RU_Fast << RADIO_MODECNF0_RU_Pos) & + RADIO_MODECNF0_RU_Msk; + + /* Set logical address 1 for TX and RX */ + NRF_RADIO->TXADDRESS = 0; + NRF_RADIO->RXADDRESSES = (1 << 0); + + /* Configure the CRC registers */ + NRF_RADIO->CRCCNF = (RADIO_CRCCNF_SKIPADDR_Skip << RADIO_CRCCNF_SKIPADDR_Pos) | RADIO_CRCCNF_LEN_Three; + + /* Configure BLE poly */ + NRF_RADIO->CRCPOLY = 0x0000065B; + + /* Configure IFS */ + NRF_RADIO->TIFS = BLE_LL_IFS; + + /* Captures tx/rx start in timer0 cc 1 and tx/rx end in timer0 cc 2 */ + NRF_PPI->CHENSET = PPI_CHEN_CH26_Msk | PPI_CHEN_CH27_Msk; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + NRF_CCM->INTENCLR = 0xffffffff; + NRF_CCM->SHORTS = CCM_SHORTS_ENDKSGEN_CRYPT_Msk; + NRF_CCM->EVENTS_ERROR = 0; + memset(g_nrf_encrypt_scratchpad, 0, sizeof(g_nrf_encrypt_scratchpad)); +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + g_ble_phy_data.phy_aar_scratch = 0; + NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0]; + NRF_AAR->INTENCLR = 0xffffffff; + NRF_AAR->EVENTS_END = 0; + NRF_AAR->EVENTS_RESOLVED = 0; + NRF_AAR->EVENTS_NOTRESOLVED = 0; + NRF_AAR->NIRK = 0; +#endif + + /* TIMER0 setup for PHY when using RTC */ + NRF_TIMER0->TASKS_STOP = 1; + NRF_TIMER0->TASKS_SHUTDOWN = 1; + NRF_TIMER0->BITMODE = 3; /* 32-bit timer */ + NRF_TIMER0->MODE = 0; /* Timer mode */ + NRF_TIMER0->PRESCALER = 4; /* gives us 1 MHz */ + + /* + * PPI setup. + * Channel 4: Captures TIMER0 in CC[3] when EVENTS_ADDRESS occurs. Used + * to cancel the wait for response timer. + * Channel 5: TIMER0 CC[3] to TASKS_DISABLE on radio. This is the wait + * for response timer. + */ + NRF_PPI->CH[4].EEP = (uint32_t)&(NRF_RADIO->EVENTS_ADDRESS); + NRF_PPI->CH[4].TEP = (uint32_t)&(NRF_TIMER0->TASKS_CAPTURE[3]); + NRF_PPI->CH[5].EEP = (uint32_t)&(NRF_TIMER0->EVENTS_COMPARE[3]); + NRF_PPI->CH[5].TEP = (uint32_t)&(NRF_RADIO->TASKS_DISABLE); + + /* Set isr in vector table and enable interrupt */ +#ifndef RIOT_VERSION + NVIC_SetPriority(RADIO_IRQn, 0); +#endif +#if MYNEWT + NVIC_SetVector(RADIO_IRQn, (uint32_t)ble_phy_isr); +#else + ble_npl_hw_set_isr(RADIO_IRQn, ble_phy_isr); +#endif + NVIC_EnableIRQ(RADIO_IRQn); + + /* Register phy statistics */ + if (!g_ble_phy_data.phy_stats_initialized) { + rc = stats_init_and_reg(STATS_HDR(ble_phy_stats), + STATS_SIZE_INIT_PARMS(ble_phy_stats, + STATS_SIZE_32), + STATS_NAME_INIT_PARMS(ble_phy_stats), + "ble_phy"); + assert(rc == 0); + + g_ble_phy_data.phy_stats_initialized = 1; + } + + ble_phy_dbg_time_setup(); + + return 0; +} + +/** + * Puts the phy into receive mode. + * + * @return int 0: success; BLE Phy error code otherwise + */ +int +ble_phy_rx(void) +{ + /* + * Check radio state. + * + * In case radio is now disabling we'll wait for it to finish, but if for + * any reason it's just in idle state we proceed with RX as usual since + * nRF52 radio can ramp-up from idle state as well. + * + * Note that TX and RX states values are the same except for 3rd bit so we + * can make a shortcut here when checking for idle state. + */ + nrf_wait_disabled(); + if ((NRF_RADIO->STATE != RADIO_STATE_STATE_Disabled) && + ((NRF_RADIO->STATE & 0x07) != RADIO_STATE_STATE_RxIdle)) { + ble_phy_disable(); + STATS_INC(ble_phy_stats, radio_state_errs); + return BLE_PHY_ERR_RADIO_STATE; + } + + /* Make sure all interrupts are disabled */ + NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL; + + /* Clear events prior to enabling receive */ + NRF_RADIO->EVENTS_END = 0; + NRF_RADIO->EVENTS_DISABLED = 0; + + /* Setup for rx */ + ble_phy_rx_xcvr_setup(); + + /* PPI to start radio automatically shall be set here */ + assert(NRF_PPI->CHEN & PPI_CHEN_CH21_Msk); + + return 0; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) +/** + * Called to enable encryption at the PHY. Note that this state will persist + * in the PHY; in other words, if you call this function you have to call + * disable so that future PHY transmits/receives will not be encrypted. + * + * @param pkt_counter + * @param iv + * @param key + * @param is_master + */ +void +ble_phy_encrypt_enable(uint64_t pkt_counter, uint8_t *iv, uint8_t *key, + uint8_t is_master) +{ + memcpy(g_nrf_ccm_data.key, key, 16); + g_nrf_ccm_data.pkt_counter = pkt_counter; + memcpy(g_nrf_ccm_data.iv, iv, 8); + g_nrf_ccm_data.dir_bit = is_master; + g_ble_phy_data.phy_encrypted = 1; + /* Enable the module (AAR cannot be on while CCM on) */ + NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Disabled; + NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Enabled; +} + +void +ble_phy_encrypt_set_pkt_cntr(uint64_t pkt_counter, int dir) +{ + g_nrf_ccm_data.pkt_counter = pkt_counter; + g_nrf_ccm_data.dir_bit = dir; +} + +void +ble_phy_encrypt_disable(void) +{ + NRF_PPI->CHENCLR = PPI_CHEN_CH25_Msk; + NRF_CCM->TASKS_STOP = 1; + NRF_CCM->EVENTS_ERROR = 0; + NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Disabled; + + g_ble_phy_data.phy_encrypted = 0; +} +#endif + +void +ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg) +{ + /* Set transmit end callback and arg */ + g_ble_phy_data.txend_cb = txend_cb; + g_ble_phy_data.txend_arg = arg; +} + +/** + * Called to set the start time of a transmission. + * + * This function is called to set the start time when we are not going from + * rx to tx automatically. + * + * NOTE: care must be taken when calling this function. The channel should + * already be set. + * + * @param cputime This is the tick at which the 1st bit of the preamble + * should be transmitted + * @param rem_usecs This is used only when the underlying timing uses a 32.768 + * kHz crystal. It is the # of usecs from the cputime tick + * at which the first bit of the preamble should be + * transmitted. + * @return int + */ +int +ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs) +{ + int rc; + + ble_phy_trace_u32x2(BLE_PHY_TRACE_ID_START_TX, cputime, rem_usecs); + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + ble_phy_mode_apply(g_ble_phy_data.phy_tx_phy_mode); +#endif + + /* XXX: This should not be necessary, but paranoia is good! */ + /* Clear timer0 compare to RXEN since we are transmitting */ + NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk; + + if (ble_phy_set_start_time(cputime, rem_usecs, true) != 0) { + STATS_INC(ble_phy_stats, tx_late); + ble_phy_disable(); + rc = BLE_PHY_ERR_TX_LATE; + } else { + /* Enable PPI to automatically start TXEN */ + NRF_PPI->CHENSET = PPI_CHEN_CH20_Msk; + rc = 0; + } + return rc; +} + +/** + * Called to set the start time of a reception + * + * This function acts a bit differently than transmit. If we are late getting + * here we will still attempt to receive. + * + * NOTE: care must be taken when calling this function. The channel should + * already be set. + * + * @param cputime + * + * @return int + */ +int +ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs) +{ + bool late = false; + int rc = 0; + + ble_phy_trace_u32x2(BLE_PHY_TRACE_ID_START_RX, cputime, rem_usecs); + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + ble_phy_mode_apply(g_ble_phy_data.phy_rx_phy_mode); +#endif + + /* XXX: This should not be necessary, but paranoia is good! */ + /* Clear timer0 compare to TXEN since we are transmitting */ + NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk; + + if (ble_phy_set_start_time(cputime, rem_usecs, false) != 0) { + STATS_INC(ble_phy_stats, rx_late); + + /* We're late so let's just try to start RX as soon as possible */ + ble_phy_set_start_now(); + + late = true; + } + + /* Enable PPI to automatically start RXEN */ + NRF_PPI->CHENSET = PPI_CHEN_CH21_Msk; + + /* Start rx */ + rc = ble_phy_rx(); + + /* + * If we enabled receiver but were late, let's return proper error code so + * caller can handle this. + */ + if (!rc && late) { + rc = BLE_PHY_ERR_RX_LATE; + } + + return rc; +} + +int +ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans) +{ + int rc; + uint8_t *dptr; + uint8_t *pktptr; + uint8_t payload_len; + uint8_t hdr_byte; + uint32_t state; + uint32_t shortcuts; + + if (g_ble_phy_data.phy_transition_late) { + ble_phy_disable(); + STATS_INC(ble_phy_stats, tx_late); + return BLE_PHY_ERR_TX_LATE; + } + + /* + * This check is to make sure that the radio is not in a state where + * it is moving to disabled state. If so, let it get there. + */ + nrf_wait_disabled(); + + /* + * XXX: Although we may not have to do this here, I clear all the PPI + * that should not be used when transmitting. Some of them are only enabled + * if encryption and/or privacy is on, but I dont care. Better to be + * paranoid, and if you are going to clear one, might as well clear them + * all. + */ + NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | PPI_CHEN_CH23_Msk | + PPI_CHEN_CH25_Msk; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + if (g_ble_phy_data.phy_encrypted) { + dptr = (uint8_t *)&g_ble_phy_enc_buf[0]; + pktptr = (uint8_t *)&g_ble_phy_tx_buf[0]; + NRF_CCM->SHORTS = CCM_SHORTS_ENDKSGEN_CRYPT_Msk; + NRF_CCM->INPTR = (uint32_t)dptr; + NRF_CCM->OUTPTR = (uint32_t)pktptr; + NRF_CCM->SCRATCHPTR = (uint32_t)&g_nrf_encrypt_scratchpad[0]; + NRF_CCM->EVENTS_ERROR = 0; + NRF_CCM->MODE = CCM_MODE_LENGTH_Msk | ble_phy_get_ccm_datarate(); + NRF_CCM->CNFPTR = (uint32_t)&g_nrf_ccm_data; + } else { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0]; +#endif + dptr = (uint8_t *)&g_ble_phy_tx_buf[0]; + pktptr = dptr; + } +#else + dptr = (uint8_t *)&g_ble_phy_tx_buf[0]; + pktptr = dptr; +#endif + + /* Set PDU payload */ + payload_len = pducb(&dptr[3], pducb_arg, &hdr_byte); + + /* RAM representation has S0, LENGTH and S1 fields. (3 bytes) */ + dptr[0] = hdr_byte; + dptr[1] = payload_len; + dptr[2] = 0; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + /* Start key-stream generation and encryption (via short) */ + if (g_ble_phy_data.phy_encrypted) { + NRF_CCM->TASKS_KSGEN = 1; + } +#endif + + NRF_RADIO->PACKETPTR = (uint32_t)pktptr; + + /* Clear the ready, end and disabled events */ + NRF_RADIO->EVENTS_READY = 0; + NRF_RADIO->EVENTS_END = 0; + NRF_RADIO->EVENTS_DISABLED = 0; + + /* Enable shortcuts for transmit start/end. */ + shortcuts = RADIO_SHORTS_END_DISABLE_Msk | RADIO_SHORTS_READY_START_Msk; + NRF_RADIO->SHORTS = shortcuts; + NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk; + + /* Set the PHY transition */ + g_ble_phy_data.phy_transition = end_trans; + + /* Set transmitted payload length */ + g_ble_phy_data.phy_tx_pyld_len = payload_len; + + /* If we already started transmitting, abort it! */ + state = NRF_RADIO->STATE; + if (state != RADIO_STATE_STATE_Tx) { + /* Set phy state to transmitting and count packet statistics */ + g_ble_phy_data.phy_state = BLE_PHY_STATE_TX; + STATS_INC(ble_phy_stats, tx_good); + STATS_INCN(ble_phy_stats, tx_bytes, payload_len + BLE_LL_PDU_HDR_LEN); + rc = BLE_ERR_SUCCESS; + } else { + ble_phy_disable(); + STATS_INC(ble_phy_stats, tx_late); + rc = BLE_PHY_ERR_RADIO_STATE; + } + + return rc; +} + +/** + * ble phy txpwr set + * + * Set the transmit output power (in dBm). + * + * NOTE: If the output power specified is within the BLE limits but outside + * the chip limits, we "rail" the power level so we dont exceed the min/max + * chip values. + * + * @param dbm Power output in dBm. + * + * @return int 0: success; anything else is an error + */ +int +ble_phy_txpwr_set(int dbm) +{ + /* "Rail" power level if outside supported range */ + dbm = ble_phy_txpower_round(dbm); + + NRF_RADIO->TXPOWER = dbm; + g_ble_phy_data.phy_txpwr_dbm = dbm; + + return 0; +} + +/** + * ble phy txpwr round + * + * Get the rounded transmit output power (in dBm). + * + * @param dbm Power output in dBm. + * + * @return int Rounded power in dBm + */ +int ble_phy_txpower_round(int dbm) +{ + /* TODO this should be per nRF52XXX */ + + /* "Rail" power level if outside supported range */ + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_0dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_0dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm; + } + + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm; +} + +/** + * ble phy set access addr + * + * Set access address. + * + * @param access_addr Access address + * + * @return int 0: success; PHY error code otherwise + */ +static int +ble_phy_set_access_addr(uint32_t access_addr) +{ + NRF_RADIO->BASE0 = (access_addr << 8); + NRF_RADIO->PREFIX0 = (NRF_RADIO->PREFIX0 & 0xFFFFFF00) | (access_addr >> 24); + + g_ble_phy_data.phy_access_address = access_addr; + + ble_phy_apply_errata_102_106_107(); + + return 0; +} + +/** + * ble phy txpwr get + * + * Get the transmit power. + * + * @return int The current PHY transmit power, in dBm + */ +int +ble_phy_txpwr_get(void) +{ + return g_ble_phy_data.phy_txpwr_dbm; +} + +void +ble_phy_set_rx_pwr_compensation(int8_t compensation) +{ + g_ble_phy_data.rx_pwr_compensation = compensation; +} + +/** + * ble phy setchan + * + * Sets the logical frequency of the transceiver. The input parameter is the + * BLE channel index (0 to 39, inclusive). The NRF frequency register works like + * this: logical frequency = 2400 + FREQ (MHz). + * + * Thus, to get a logical frequency of 2402 MHz, you would program the + * FREQUENCY register to 2. + * + * @param chan This is the Data Channel Index or Advertising Channel index + * + * @return int 0: success; PHY error code otherwise + */ +int +ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit) +{ + assert(chan < BLE_PHY_NUM_CHANS); + + /* Check for valid channel range */ + if (chan >= BLE_PHY_NUM_CHANS) { + return BLE_PHY_ERR_INV_PARAM; + } + + /* Set current access address */ + ble_phy_set_access_addr(access_addr); + + /* Configure crcinit */ + NRF_RADIO->CRCINIT = crcinit; + + /* Set the frequency and the data whitening initial value */ + g_ble_phy_data.phy_chan = chan; + NRF_RADIO->FREQUENCY = g_ble_phy_chan_freq[chan]; + NRF_RADIO->DATAWHITEIV = chan; + + return 0; +} + +/** + * Stop the timer used to count microseconds when using RTC for cputime + */ +static void +ble_phy_stop_usec_timer(void) +{ + NRF_TIMER0->TASKS_STOP = 1; + NRF_TIMER0->TASKS_SHUTDOWN = 1; + NRF_RTC0->EVTENCLR = RTC_EVTENSET_COMPARE0_Msk; +} + +/** + * ble phy disable irq and ppi + * + * This routine is to be called when reception was stopped due to either a + * wait for response timeout or a packet being received and the phy is to be + * restarted in receive mode. Generally, the disable routine is called to stop + * the phy. + */ +static void +ble_phy_disable_irq_and_ppi(void) +{ + NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL; + NRF_RADIO->SHORTS = 0; + NRF_RADIO->TASKS_DISABLE = 1; + NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | PPI_CHEN_CH20_Msk | + PPI_CHEN_CH21_Msk | PPI_CHEN_CH23_Msk | + PPI_CHEN_CH25_Msk | PPI_CHEN_CH31_Msk; + NVIC_ClearPendingIRQ(RADIO_IRQn); + g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE; +} + +void +ble_phy_restart_rx(void) +{ + ble_phy_stop_usec_timer(); + ble_phy_disable_irq_and_ppi(); + + ble_phy_set_start_now(); + /* Enable PPI to automatically start RXEN */ + NRF_PPI->CHENSET = PPI_CHEN_CH21_Msk; + + ble_phy_rx(); +} + +/** + * ble phy disable + * + * Disables the PHY. This should be called when an event is over. It stops + * the usec timer (if used), disables interrupts, disables the RADIO, disables + * PPI and sets state to idle. + */ +void +ble_phy_disable(void) +{ + ble_phy_trace_void(BLE_PHY_TRACE_ID_DISABLE); + + ble_phy_stop_usec_timer(); + ble_phy_disable_irq_and_ppi(); +} + +/* Gets the current access address */ +uint32_t ble_phy_access_addr_get(void) +{ + return g_ble_phy_data.phy_access_address; +} + +/** + * Return the phy state + * + * @return int The current PHY state. + */ +int +ble_phy_state_get(void) +{ + return g_ble_phy_data.phy_state; +} + +/** + * Called to see if a reception has started + * + * @return int + */ +int +ble_phy_rx_started(void) +{ + return g_ble_phy_data.phy_rx_started; +} + +/** + * Return the transceiver state + * + * @return int transceiver state. + */ +uint8_t +ble_phy_xcvr_state_get(void) +{ + uint32_t state; + state = NRF_RADIO->STATE; + return (uint8_t)state; +} + +/** + * Called to return the maximum data pdu payload length supported by the + * phy. For this chip, if encryption is enabled, the maximum payload is 27 + * bytes. + * + * @return uint8_t Maximum data channel PDU payload size supported + */ +uint8_t +ble_phy_max_data_pdu_pyld(void) +{ + return BLE_LL_DATA_PDU_MAX_PYLD; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) +void +ble_phy_resolv_list_enable(void) +{ + NRF_AAR->NIRK = (uint32_t)g_nrf_num_irks; + g_ble_phy_data.phy_privacy = 1; +} + +void +ble_phy_resolv_list_disable(void) +{ + g_ble_phy_data.phy_privacy = 0; +} +#endif + +#if MYNEWT_VAL(BLE_LL_DTM) +void ble_phy_enable_dtm(void) +{ + /* When DTM is enabled we need to disable whitening as per + * Bluetooth v5.0 Vol 6. Part F. 4.1.1 + */ + NRF_RADIO->PCNF1 &= ~RADIO_PCNF1_WHITEEN_Msk; +} + +void ble_phy_disable_dtm(void) +{ + /* Enable whitening */ + NRF_RADIO->PCNF1 |= RADIO_PCNF1_WHITEEN_Msk; +} +#endif + +void +ble_phy_rfclk_enable(void) +{ +#if MYNEWT + nrf52_clock_hfxo_request(); +#else + NRF_CLOCK->TASKS_HFCLKSTART = 1; +#endif +} + +void +ble_phy_rfclk_disable(void) +{ +#if MYNEWT + nrf52_clock_hfxo_release(); +#else + NRF_CLOCK->TASKS_HFCLKSTOP = 1; +#endif +} + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_phy_trace.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_phy_trace.c new file mode 100644 index 000000000..84dbf4def --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_phy_trace.c @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#if defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) + +#include +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/os/os_trace_api.h" + +#if MYNEWT_VAL(BLE_PHY_SYSVIEW) + +static os_trace_module_t g_ble_phy_trace_mod; +uint32_t ble_phy_trace_off; + +static void +ble_phy_trace_module_send_desc(void) +{ + os_trace_module_desc(&g_ble_phy_trace_mod, "0 phy_set_tx cputime=%u usecs=%u"); + os_trace_module_desc(&g_ble_phy_trace_mod, "1 phy_set_rx cputime=%u usecs=%u"); + os_trace_module_desc(&g_ble_phy_trace_mod, "2 phy_disable"); +} + +void +ble_phy_trace_init(void) +{ + ble_phy_trace_off = + os_trace_module_register(&g_ble_phy_trace_mod, "ble_phy", 3, + ble_phy_trace_module_send_desc); +} +#endif +#endif \ No newline at end of file diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/syscfg.yml new file mode 100644 index 000000000..ce5123721 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/syscfg.yml @@ -0,0 +1,75 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +syscfg.defs: + BLE_PHY_SYSVIEW: + description: > + Enable SystemView tracing module for radio driver. + value: 0 + + BLE_PHY_CODED_RX_IFS_EXTRA_MARGIN: + description: > + This defines additional margin for T_IFS tolerance while in + RX on coded phy to allow maintaining connections with some + controllers that exceed proper T_IFS (150 usecs) by more + than allowed 2 usecs. + This value shall be only used for debugging purposes. It is + strongly recommended to keep this settings at default value + to ensure compliance with specification. + value: 0 + BLE_PHY_DBG_TIME_TXRXEN_READY_PIN: + description: > + When set to proper GPIO pin number, this pin will be set + to high state when radio is enabled using PPI channels + 20 or 21 and back to low state on radio EVENTS_READY. + This can be used to measure radio ram-up time. + value: -1 + + BLE_PHY_DBG_TIME_ADDRESS_END_PIN: + description: > + When set to proper GPIO pin number, this pin will be set + to high state on radio EVENTS_ADDRESS and back to low state + on radio EVENTS_END. + This can be used to measure radio pipeline delays. + value: -1 + + BLE_PHY_DBG_TIME_WFR_PIN: + description: > + When set to proper GPIO pin number, this pin will be set + to high state on radio EVENTS_RXREADY and back to low + state when wfr timer expires. + This can be used to check if wfr is calculated properly. + value: -1 + + BLE_PHY_NRF52840_ERRATA_164: + description: > + Enable workaround for anomaly 164 found in nRF52840. + "[164] RADIO: Low selectivity in long range mode" + This shall be only enabled for: + - nRF52840 Engineering A + value: 0 + + BLE_PHY_NRF52840_ERRATA_191: + description: > + Enable workaround for anomaly 191 found in nRF52840. + "[191] RADIO: High packet error rate in BLE Long Range mode" + This shall be only enabled for: + - nRF52840 Engineering B + - nRF52840 Engineering C + - nRF52840 Rev 1 (final silicon) + value: 1 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_att.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_att.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/host/ble_att.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_att.h index 391a992ae..ceca35179 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_att.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_att.h @@ -27,7 +27,7 @@ * @{ */ -#include "os/queue.h" +#include "nimble/porting/nimble/include/os/queue.h" #ifdef __cplusplus extern "C" { #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_eddystone.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_eddystone.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/host/ble_eddystone.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_eddystone.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_gap.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_gap.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/host/ble_gap.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_gap.h index ed7fbb128..edaf3bc4d 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_gap.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_gap.h @@ -28,9 +28,9 @@ */ #include -#include "host/ble_hs.h" -#include "host/ble_hs_adv.h" -#include "syscfg/syscfg.h" +#include "ble_hs.h" +#include "ble_hs_adv.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" #ifdef __cplusplus extern "C" { @@ -1821,6 +1821,22 @@ int ble_gap_wl_tx_rmv(const ble_addr_t *addrs); int ble_gap_update_params(uint16_t conn_handle, const struct ble_gap_upd_params *params); +/** + * Configure LE Data Length in controller (OGF = 0x08, OCF = 0x0022). + * + * @param conn_handle Connection handle. + * @param tx_octets The preferred value of payload octets that the Controller + * should use for a new connection (Range + * 0x001B-0x00FB). + * @param tx_time The preferred maximum number of microseconds that the local Controller + * should use to transmit a single link layer packet + * (Range 0x0148-0x4290). + * + * @return 0 on success, + * other error code on failure. + */ +int ble_gap_set_data_len(uint16_t conn_handle, uint16_t tx_octets, uint16_t tx_time); + /** * Initiates the GAP security procedure. * diff --git a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_gatt.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_gatt.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/host/ble_gatt.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_gatt.h index d5c3269f0..ee8f177f8 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_gatt.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_gatt.h @@ -28,8 +28,8 @@ */ #include -#include "host/ble_att.h" -#include "host/ble_uuid.h" +#include "ble_att.h" +#include "ble_uuid.h" #ifdef __cplusplus extern "C" { #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs.h similarity index 96% rename from lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs.h index 43979ba57..f24b8a9e0 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs.h @@ -27,23 +27,23 @@ */ #include -#include "nimble/hci_common.h" -#include "host/ble_att.h" -#include "host/ble_eddystone.h" -#include "host/ble_gap.h" -#include "host/ble_gatt.h" -#include "host/ble_hs_adv.h" -#include "host/ble_hs_id.h" -#include "host/ble_hs_hci.h" -#include "host/ble_hs_log.h" -#include "host/ble_hs_mbuf.h" -#include "host/ble_hs_stop.h" -#include "host/ble_ibeacon.h" -#include "host/ble_l2cap.h" -#include "host/ble_sm.h" -#include "host/ble_store.h" -#include "host/ble_uuid.h" -#include "nimble/nimble_npl.h" +#include "nimble/nimble/include/nimble/hci_common.h" +#include "ble_att.h" +#include "ble_eddystone.h" +#include "ble_gap.h" +#include "ble_gatt.h" +#include "ble_hs_adv.h" +#include "ble_hs_id.h" +#include "ble_hs_hci.h" +#include "ble_hs_log.h" +#include "ble_hs_mbuf.h" +#include "ble_hs_stop.h" +#include "ble_ibeacon.h" +#include "ble_l2cap.h" +#include "ble_sm.h" +#include "ble_store.h" +#include "ble_uuid.h" +#include "nimble/nimble/include/nimble/nimble_npl.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_adv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_adv.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_adv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_adv.h index e3b6ea709..ae2965328 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_adv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_adv.h @@ -21,7 +21,7 @@ #define H_BLE_HS_ADV_ #include -#include "host/ble_uuid.h" +#include "ble_uuid.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_hci.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_hci.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_hci.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_hci.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_id.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_id.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_id.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_id.h index c96bd20f5..568303412 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_id.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_id.h @@ -28,7 +28,7 @@ */ #include -#include "nimble/ble.h" +#include "nimble/nimble/include/nimble/ble.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_log.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_log.h similarity index 92% rename from lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_log.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_log.h index 8d0a4596e..303b53c6e 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_log.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_log.h @@ -20,11 +20,11 @@ #ifndef H_BLE_HS_LOG_ #define H_BLE_HS_LOG_ -#include "modlog/modlog.h" +#include "nimble/porting/nimble/include/modlog/modlog.h" /* Only include the logcfg header if this version of newt can generate it. */ #if MYNEWT_VAL(NEWT_FEATURE_LOGCFG) -#include "logcfg/logcfg.h" +#include "nimble/porting/nimble/include/logcfg/logcfg.h" #endif #ifdef __cplusplus diff --git a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_mbuf.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_mbuf.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_mbuf.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_mbuf.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_pvcy.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_pvcy.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_pvcy.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_pvcy.h index 19087f220..26450f4f8 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_pvcy.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_pvcy.h @@ -22,7 +22,7 @@ #ifndef H_BLE_HS_PVCY_ #define H_BLE_HS_PVCY_ -#include "host/ble_hs.h" +#include "ble_hs.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_stop.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_stop.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/host/ble_hs_stop.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_stop.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_ibeacon.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_ibeacon.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/host/ble_ibeacon.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_ibeacon.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_l2cap.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_l2cap.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/host/ble_l2cap.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_l2cap.h index aef9682cc..9d92c08f1 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_l2cap.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_l2cap.h @@ -20,7 +20,7 @@ #ifndef H_BLE_L2CAP_ #define H_BLE_L2CAP_ -#include "nimble/nimble_opt.h" +#include "nimble/nimble/include/nimble/nimble_opt.h" #ifdef __cplusplus extern "C" { #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_monitor.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_monitor.h similarity index 95% rename from lib/libesp32_div/NimBLE-Arduino/src/host/ble_monitor.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_monitor.h index 61722f7db..418d4e379 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_monitor.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_monitor.h @@ -20,7 +20,7 @@ #ifndef H_BLE_MONITOR_ #define H_BLE_MONITOR_ -#include +#include "nimble/porting/nimble/include/syscfg/syscfg.h" #undef BLE_MONITOR #define BLE_MONITOR (MYNEWT_VAL(BLE_MONITOR_UART) || MYNEWT_VAL(BLE_MONITOR_RTT)) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_sm.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_sm.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/host/ble_sm.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_sm.h index ceebb8564..42414d584 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_sm.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_sm.h @@ -21,7 +21,7 @@ #define H_BLE_SM_ #include -#include "syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_store.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_store.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/host/ble_store.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_store.h index a3eca5d23..8e6721bf3 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_store.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_store.h @@ -21,7 +21,7 @@ #define H_BLE_STORE_ #include -#include "nimble/ble.h" +#include "nimble/nimble/include/nimble/ble.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/host/ble_uuid.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_uuid.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/host/ble_uuid.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_uuid.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/mesh/access.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/access.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/mesh/access.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/access.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/mesh/cfg_cli.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/cfg_cli.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/mesh/cfg_cli.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/cfg_cli.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/mesh/cfg_srv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/cfg_srv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/mesh/cfg_srv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/cfg_srv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/mesh/glue.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/glue.h similarity index 95% rename from lib/libesp32_div/NimBLE-Arduino/src/mesh/glue.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/glue.h index 388ecba39..f50b6ece8 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/mesh/glue.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/glue.h @@ -23,19 +23,19 @@ #include #include -#include "syscfg/syscfg.h" -#include "logcfg/logcfg.h" -#include "modlog/modlog.h" -#include "nimble/nimble_npl.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/logcfg/logcfg.h" +#include "nimble/porting/nimble/include/modlog/modlog.h" +#include "nimble/nimble/include/nimble/nimble_npl.h" -#include "os/os_mbuf.h" -#include "os/queue.h" +#include "nimble/porting/nimble/include/os/os_mbuf.h" +#include "nimble/porting/nimble/include/os/queue.h" -#include "nimble/ble.h" -#include "host/ble_hs.h" -#include "host/ble_uuid.h" -#include "../src/ble_sm_priv.h" -#include "../src/ble_hs_hci_priv.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/host/include/host/ble_hs.h" +#include "nimble/nimble/host/include/host/ble_uuid.h" +#include "nimble/nimble/host/src/ble_sm_priv.h" +#include "nimble/nimble/host/src/ble_hs_hci_priv.h" #if MYNEWT_VAL(BLE_CRYPTO_STACK_MBEDTLS) #include "mbedtls/aes.h" @@ -47,11 +47,11 @@ #include "mbedtls/ecp.h" #else -#include "tinycrypt/aes.h" -#include "tinycrypt/constants.h" -#include "tinycrypt/utils.h" -#include "tinycrypt/cmac_mode.h" -#include "tinycrypt/ecc_dh.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/aes.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/constants.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/utils.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/cmac_mode.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/ecc_dh.h" #endif #if MYNEWT_VAL(BLE_MESH_SETTINGS) @@ -359,8 +359,6 @@ static inline void net_buf_simple_restore(struct os_mbuf *buf, static inline void sys_memcpy_swap(void *dst, const void *src, size_t length) { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpointer-arith" __ASSERT(((src < dst && (src + length) <= dst) || (src > dst && (dst + length) <= src)), "Source and destination buffers must not overlap"); @@ -370,7 +368,6 @@ static inline void sys_memcpy_swap(void *dst, const void *src, size_t length) for (; length > 0; length--) { *((u8_t *)dst++) = *((u8_t *)src--); } -#pragma GCC diagnostic pop } #define popcount(x) __builtin_popcount(x) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/mesh/health_cli.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/health_cli.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/mesh/health_cli.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/health_cli.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/mesh/health_srv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/health_srv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/mesh/health_srv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/health_srv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/mesh/main.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/main.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/mesh/main.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/main.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/mesh/mesh.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/mesh.h similarity index 78% rename from lib/libesp32_div/NimBLE-Arduino/src/mesh/mesh.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/mesh.h index 9ba63ef0e..77b2871fc 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/mesh/mesh.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/mesh.h @@ -11,8 +11,8 @@ #define __BT_MESH_H #include -#include "syscfg/syscfg.h" -#include "os/os_mbuf.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/os/os_mbuf.h" #include "glue.h" #include "access.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/mesh/model_cli.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/model_cli.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/mesh/model_cli.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/model_cli.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/mesh/model_srv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/model_srv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/mesh/model_srv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/model_srv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/mesh/porting.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/porting.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/mesh/porting.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/porting.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/mesh/proxy.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/proxy.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/mesh/proxy.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/proxy.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/mesh/slist.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/slist.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/mesh/slist.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/slist.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/mesh/testing.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/testing.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/mesh/testing.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/testing.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/pkg.yml new file mode 100644 index 000000000..44cc0c732 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/pkg.yml @@ -0,0 +1,49 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: nimble/host/mesh +pkg.description: Bluetooth Mesh +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - ble + - bluetooth + - mesh + +pkg.deps: + - "@apache-mynewt-core/kernel/os" + - "@apache-mynewt-core/util/mem" + - "@apache-mynewt-core/crypto/tinycrypt" + - nimble + - nimble/host + +pkg.deps.BLE_MESH_SHELL: + - "@apache-mynewt-core/sys/shell" + +pkg.deps.BLE_MESH_SETTINGS: + - "@apache-mynewt-core/encoding/base64" + - "@apache-mynewt-core/sys/config" + +pkg.req_apis: + - log + - stats + +pkg.init: + bt_mesh_register_gatt: 'MYNEWT_VAL(BLE_MESH_SYSINIT_STAGE)' + ble_mesh_shell_init: 'MYNEWT_VAL(BLE_MESH_SYSINIT_STAGE_SHELL)' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/access.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/access.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/access.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/access.c index ff8e99997..37580b400 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/access.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/access.c @@ -6,13 +6,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#if MYNEWT_VAL(BLE_MESH) + #define MESH_LOG_MODULE BLE_MESH_ACCESS_LOG #include -#include +#include "nimble/porting/nimble/include/os/os_mbuf.h" -#include "mesh/mesh.h" +#include "../include/mesh/mesh.h" #include "mesh_priv.h" #include "adv.h" @@ -22,7 +24,7 @@ #include "access.h" #include "foundation.h" #if MYNEWT_VAL(BLE_MESH_SHELL_MODELS) -#include "mesh/model_cli.h" +#include "../include/mesh/model_cli.h" #endif static const struct bt_mesh_comp *dev_comp; @@ -854,3 +856,4 @@ int bt_mesh_model_extend(struct bt_mesh_model *mod, return 0; } #endif +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/access.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/access.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/access.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/access.h index 48514983f..03081b9ad 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/access.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/access.h @@ -9,7 +9,7 @@ #ifndef __ACCESS_H__ #define __ACCESS_H__ -#include "mesh/mesh.h" +#include "../include/mesh/mesh.h" /* bt_mesh_model.flags */ enum { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/adv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/adv.c similarity index 94% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/adv.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/adv.c index b8fb1c7de..b9d290176 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/adv.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/adv.c @@ -7,16 +7,17 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#if MYNEWT_VAL(BLE_MESH) + #define MESH_LOG_MODULE BLE_MESH_ADV_LOG -#include "mesh/mesh.h" -#include "host/ble_hs_adv.h" -#include "host/ble_gap.h" -#include "nimble/hci_common.h" -#include "mesh/porting.h" -#include "nimble/nimble_port.h" - +#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/include/host/ble_hs_adv.h" +#include "nimble/nimble/host/include/host/ble_gap.h" +#include "nimble/nimble/include/nimble/hci_common.h" +#include "../include/mesh/porting.h" +#include "nimble/porting/nimble/include/nimble/nimble_port.h" #include "adv.h" #include "net.h" #include "foundation.h" @@ -337,9 +338,12 @@ void bt_mesh_adv_init(void) os_task_init(&adv_task, "mesh_adv", mesh_adv_thread, NULL, MYNEWT_VAL(BLE_MESH_ADV_TASK_PRIO), OS_WAIT_FOREVER, g_blemesh_stack, ADV_STACK_SIZE); -#else +#elif ESP_PLATFORM xTaskCreatePinnedToCore(mesh_adv_thread, "mesh_adv", 2768, NULL, (configMAX_PRIORITIES - 5), &adv_task_h, NIMBLE_CORE); +#else + xTaskCreate(mesh_adv_thread, "mesh_adv", MYNEWT_VAL(BLE_MESH_ADV_STACK_SIZE), + NULL, MYNEWT_VAL(BLE_MESH_ADV_TASK_PRIO), &adv_task_h); #endif /* For BT5 controllers we can have fast advertising interval */ @@ -443,3 +447,4 @@ int bt_mesh_scan_disable(void) return 0; } +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/adv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/adv.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/adv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/adv.h index 4d0f7d8ba..40e65e5f4 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/adv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/adv.h @@ -10,7 +10,7 @@ #define __ADV_H__ /* Maximum advertising data payload for a single data type */ -#include "mesh/mesh.h" +#include "../include/mesh/mesh.h" #define BT_MESH_ADV(om) (*(struct bt_mesh_adv **) OS_MBUF_USRHDR(om)) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/atomic.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/atomic.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/atomic.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/atomic.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/beacon.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/beacon.c index cd540aa8c..89ee1a086 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/beacon.c @@ -6,13 +6,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#if MYNEWT_VAL(BLE_MESH) + #define MESH_LOG_MODULE BLE_MESH_BEACON_LOG #include #include -#include "os/os_mbuf.h" -#include "mesh/mesh.h" +#include "nimble/porting/nimble/include/os/os_mbuf.h" +#include "../include/mesh/mesh.h" #include "adv.h" #include "mesh_priv.h" @@ -439,3 +441,4 @@ void bt_mesh_beacon_disable(void) k_delayed_work_cancel(&beacon_timer); } } +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/beacon.h similarity index 89% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/beacon.h index ac4bfed8a..08fd88d96 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/beacon.h @@ -9,7 +9,7 @@ #ifndef __BEACON_H__ #define __BEACON_H__ -#include "os/os_mbuf.h" +#include "nimble/porting/nimble/include/os/os_mbuf.h" void bt_mesh_beacon_enable(void); void bt_mesh_beacon_disable(void); diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_cli.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg_cli.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_cli.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg_cli.c index 2c2f6c3ff..d2596c434 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_cli.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg_cli.c @@ -6,11 +6,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#if MYNEWT_VAL(BLE_MESH) + #define MESH_LOG_MODULE BLE_MESH_MODEL_LOG #if MYNEWT_VAL(BLE_MESH_CFG_CLI) -#include "mesh/mesh.h" +#include "../include/mesh/mesh.h" #include #include @@ -1496,3 +1498,4 @@ void bt_mesh_cfg_cli_timeout_set(s32_t timeout) } #endif +#endif \ No newline at end of file diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_srv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg_srv.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_srv.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg_srv.c index 57aac90a3..f5de01cbf 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_srv.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg_srv.c @@ -6,14 +6,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#if MYNEWT_VAL(BLE_MESH) + #define MESH_LOG_MODULE BLE_MESH_MODEL_LOG #include #include #include -#include "mesh/mesh.h" +#include "../include/mesh/mesh.h" #include "mesh_priv.h" #include "adv.h" @@ -3617,3 +3619,4 @@ void bt_mesh_subnet_del(struct bt_mesh_subnet *sub, bool store) memset(sub, 0, sizeof(*sub)); sub->net_idx = BT_MESH_KEY_UNUSED; } +#endif \ No newline at end of file diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/crypto.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/crypto.c index 20b110378..425897630 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/crypto.c @@ -6,13 +6,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#if MYNEWT_VAL(BLE_MESH) + #define MESH_LOG_MODULE BLE_MESH_CRYPTO_LOG #include #include #include -#include "syscfg/syscfg.h" #if (MYNEWT_VAL(BLE_CRYPTO_STACK_MBEDTLS)) #include "mbedtls/aes.h" @@ -24,11 +25,11 @@ #include "mbedtls/ecp.h" #else -#include -#include -#include -#include -#include +#include "nimble/ext/tinycrypt/include/tinycrypt/constants.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/utils.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/aes.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/cmac_mode.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/ccm_mode.h" #endif #include "crypto.h" @@ -965,3 +966,4 @@ int bt_mesh_beacon_auth(const u8_t beacon_key[16], u8_t flags, return err; } +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/crypto.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/crypto.h index 745cf324a..8af371c60 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/crypto.h @@ -8,7 +8,7 @@ #ifndef __CRYPTO_H__ #define __CRYPTO_H__ -#include "mesh/mesh.h" +#include "../include/mesh/mesh.h" struct bt_mesh_sg { const void *data; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/foundation.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/foundation.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/foundation.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/foundation.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/friend.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/friend.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/friend.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/friend.c index 9056a8658..c10a93ec7 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/friend.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/friend.c @@ -6,7 +6,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#if MYNEWT_VAL(BLE_MESH) + #define MESH_LOG_MODULE BLE_MESH_CRYPTO_LOG #if MYNEWT_VAL(BLE_MESH_FRIEND) @@ -15,9 +17,9 @@ #include #include -#include "mesh/mesh.h" -#include "mesh/slist.h" -#include "mesh_priv.h" +#include "../include/mesh/mesh.h" +#include "../include/mesh/slist.h" +#include "../include/mesh_priv.h" #include "crypto.h" #include "adv.h" #include "net.h" @@ -1649,3 +1651,4 @@ void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, u16_t src, } #endif /* MYNEWT_VAL(BLE_MESH_FRIEND) */ +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/friend.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/friend.h similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/friend.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/friend.h index 10ffa8190..361c1f097 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/friend.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/friend.h @@ -9,7 +9,7 @@ #ifndef __FRIEND_H__ #define __FRIEND_H__ -#include "mesh/mesh.h" +#include "../include/mesh/mesh.h" enum bt_mesh_friend_pdu_type { BT_MESH_FRIEND_PDU_SINGLE, diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/glue.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/glue.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/glue.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/glue.c index 7da73d15b..14e515b91 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/glue.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/glue.c @@ -17,13 +17,15 @@ * under the License. */ -#include "syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#if MYNEWT_VAL(BLE_MESH) + #define MESH_LOG_MODULE BLE_MESH_LOG -#include "mesh/glue.h" +#include "../include/mesh/glue.h" #include "adv.h" #ifndef MYNEWT -#include "nimble/nimble_port.h" +#include "nimble/porting/nimble/include/nimble/nimble_port.h" #endif #if MYNEWT_VAL(BLE_MESH_SETTINGS) @@ -890,4 +892,4 @@ char *settings_str_from_bytes(const void *vp, int vp_len, } #endif /* MYNEWT_VAL(BLE_MESH_SETTINGS) */ - +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/health_cli.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/health_cli.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/health_cli.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/health_cli.c index 193279c28..3fc29e52f 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/health_cli.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/health_cli.c @@ -6,20 +6,22 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#if MYNEWT_VAL(BLE_MESH) + #define MESH_LOG_MODULE BLE_MESH_MODEL_LOG #include #include #include -#include "mesh/mesh.h" +#include "../include/mesh/mesh.h" #include "mesh_priv.h" #include "adv.h" #include "net.h" #include "transport.h" #include "foundation.h" -#include "mesh/health_cli.h" +#include "../include/mesh/health_cli.h" static s32_t msg_timeout = K_SECONDS(5); @@ -554,3 +556,4 @@ static int health_cli_init(struct bt_mesh_model *model) const struct bt_mesh_model_cb bt_mesh_health_cli_cb = { .init = health_cli_init, }; +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/health_srv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/health_srv.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/health_srv.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/health_srv.c index 16de83a99..7063d9203 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/health_srv.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/health_srv.c @@ -6,14 +6,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#if MYNEWT_VAL(BLE_MESH) + #define MESH_LOG_MODULE BLE_MESH_MODEL_LOG #include #include #include -#include "mesh/mesh.h" +#include "../include/mesh/mesh.h" #include "mesh_priv.h" #include "adv.h" #include "net.h" @@ -451,3 +453,4 @@ void bt_mesh_attention(struct bt_mesh_model *model, u8_t time) } } } +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/light_model.c similarity index 87% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/light_model.c index b6d838188..a390bf86b 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/light_model.c @@ -1,8 +1,9 @@ -#include "syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#if MYNEWT_VAL(BLE_MESH) -#include "mesh/mesh.h" -#include "console/console.h" +#include "../include/mesh/mesh.h" +#include "nimble/console/console.h" #include "light_model.h" @@ -55,4 +56,4 @@ int light_model_light_lightness_set(struct bt_mesh_model *model, s16_t lightness { return light_model_gen_level_set(model, lightness); } - +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/light_model.h similarity index 87% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/light_model.h index 95fcdb786..f3b1f7cb7 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/light_model.h @@ -6,8 +6,8 @@ #ifndef __BT_MESH_LIGHT_MODEL_H #define __BT_MESH_LIGHT_MODEL_H -#include "syscfg/syscfg.h" -#include "mesh/mesh.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "../include/mesh/mesh.h" int light_model_gen_onoff_get(struct bt_mesh_model *model, u8_t *state); int light_model_gen_onoff_set(struct bt_mesh_model *model, u8_t state); diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/lpn.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/lpn.c index ec012a5f0..5bb64b97d 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/lpn.c @@ -6,14 +6,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#if MYNEWT_VAL(BLE_MESH) + #define MESH_LOG_MODULE BLE_MESH_LOW_POWER_LOG #if MYNEWT_VAL(BLE_MESH_LOW_POWER) #include -#include "mesh/mesh.h" +#include "../include/mesh/mesh.h" #include "mesh_priv.h" #include "crypto.h" #include "adv.h" @@ -1054,3 +1056,4 @@ int bt_mesh_lpn_init(void) } #endif /* MYNEWT_VAL(BLE_MESH_LOW_POWER) */ +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/lpn.h similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/lpn.h index 0ff6c9cfd..e53c81d3d 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/lpn.h @@ -8,7 +8,7 @@ #ifndef __LPN_H__ #define __LPN_H__ -#include "mesh/mesh.h" +#include "../include/mesh/mesh.h" int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx, struct os_mbuf *buf); diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/mesh.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/mesh.c similarity index 96% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/mesh.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/mesh.c index 52fbdbf66..7ad1264ae 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/mesh.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/mesh.c @@ -6,15 +6,17 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#if MYNEWT_VAL(BLE_MESH) + #define MESH_LOG_MODULE BLE_MESH_LOG #include #include -#include "os/os_mbuf.h" -#include "mesh/mesh.h" -#include "host/ble_uuid.h" +#include "nimble/porting/nimble/include/os/os_mbuf.h" +#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/include/host/ble_uuid.h" #include "adv.h" #include "prov.h" @@ -359,3 +361,4 @@ int bt_mesh_init(uint8_t own_addr_type, const struct bt_mesh_prov *prov, return 0; } +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/mesh_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/mesh_priv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/mesh_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/mesh_priv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/model_cli.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/model_cli.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/model_cli.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/model_cli.c index b00cfa520..c8b10df0c 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/model_cli.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/model_cli.c @@ -4,11 +4,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#if MYNEWT_VAL(BLE_MESH) + #define MESH_LOG_MODULE BLE_MESH_MODEL_LOG -#include "mesh/mesh.h" -#include "mesh/model_cli.h" +#include "../include/mesh/mesh.h" +#include "../include/mesh/model_cli.h" #include "mesh_priv.h" static s32_t msg_timeout = K_SECONDS(5); @@ -298,4 +300,4 @@ done: os_mbuf_free_chain(msg); return err; } - +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/model_srv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/model_srv.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/model_srv.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/model_srv.c index 5f5a8df42..e7bbf38d0 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/model_srv.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/model_srv.c @@ -4,11 +4,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#if MYNEWT_VAL(BLE_MESH) + #define MESH_LOG_MODULE BLE_MESH_MODEL_LOG -#include "mesh/mesh.h" -#include "mesh/model_srv.h" +#include "../include/mesh/mesh.h" +#include "../include/mesh/model_srv.h" #include "mesh_priv.h" static struct bt_mesh_gen_onoff_srv *gen_onoff_srv; @@ -264,3 +266,4 @@ static int lightness_srv_init(struct bt_mesh_model *model) const struct bt_mesh_model_cb light_lightness_srv_cb = { .init = lightness_srv_init, }; +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/net.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/net.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/net.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/net.c index cf11c2d4f..b8e48d6ed 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/net.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/net.c @@ -6,15 +6,17 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#if MYNEWT_VAL(BLE_MESH) + #define MESH_LOG_MODULE BLE_MESH_NET_LOG #include #include #include -#include "os/os_mbuf.h" -#include "mesh/mesh.h" +#include "nimble/porting/nimble/include/os/os_mbuf.h" +#include "../include/mesh/mesh.h" #include "crypto.h" #include "adv.h" @@ -254,8 +256,7 @@ int friend_cred_set(struct friend_cred *cred, u8_t idx, const u8_t net_key[16]) void friend_cred_refresh(u16_t net_idx) { int i; -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wtype-limits" + for (i = 0; i < ARRAY_SIZE(friend_cred); i++) { struct friend_cred *cred = &friend_cred[i]; @@ -265,7 +266,6 @@ void friend_cred_refresh(u16_t net_idx) sizeof(cred->cred[0])); } } -#pragma GCC diagnostic pop } int friend_cred_update(struct bt_mesh_subnet *sub) @@ -273,8 +273,7 @@ int friend_cred_update(struct bt_mesh_subnet *sub) int err, i; BT_DBG("net_idx 0x%04x", sub->net_idx); -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wtype-limits" + for (i = 0; i < ARRAY_SIZE(friend_cred); i++) { struct friend_cred *cred = &friend_cred[i]; @@ -288,7 +287,7 @@ int friend_cred_update(struct bt_mesh_subnet *sub) return err; } } -#pragma GCC diagnostic pop + return 0; } @@ -299,8 +298,7 @@ struct friend_cred *friend_cred_create(struct bt_mesh_subnet *sub, u16_t addr, int i, err; BT_DBG("net_idx 0x%04x addr 0x%04x", sub->net_idx, addr); -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wtype-limits" + for (cred = NULL, i = 0; i < ARRAY_SIZE(friend_cred); i++) { if ((friend_cred[i].addr == BT_MESH_ADDR_UNASSIGNED) || (friend_cred[i].addr == addr && @@ -309,7 +307,7 @@ struct friend_cred *friend_cred_create(struct bt_mesh_subnet *sub, u16_t addr, break; } } -#pragma GCC diagnostic pop + if (!cred) { BT_WARN("No free friend credential slots"); return NULL; @@ -349,8 +347,7 @@ void friend_cred_clear(struct friend_cred *cred) int friend_cred_del(u16_t net_idx, u16_t addr) { int i; -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wtype-limits" + for (i = 0; i < ARRAY_SIZE(friend_cred); i++) { struct friend_cred *cred = &friend_cred[i]; @@ -359,7 +356,7 @@ int friend_cred_del(u16_t net_idx, u16_t addr) return 0; } } -#pragma GCC diagnostic pop + return -ENOENT; } @@ -369,8 +366,7 @@ int friend_cred_get(struct bt_mesh_subnet *sub, u16_t addr, u8_t *nid, int i; BT_DBG("net_idx 0x%04x addr 0x%04x", sub->net_idx, addr); -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wtype-limits" + for (i = 0; i < ARRAY_SIZE(friend_cred); i++) { struct friend_cred *cred = &friend_cred[i]; @@ -396,7 +392,7 @@ int friend_cred_get(struct bt_mesh_subnet *sub, u16_t addr, u8_t *nid, return 0; } -#pragma GCC diagnostic pop + return -ENOENT; } @@ -1030,8 +1026,7 @@ static int friend_decrypt(struct bt_mesh_subnet *sub, const u8_t *data, int i; BT_DBG("NID 0x%02x net_idx 0x%04x", NID(data), sub->net_idx); -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wtype-limits" + for (i = 0; i < ARRAY_SIZE(friend_cred); i++) { struct friend_cred *cred = &friend_cred[i]; @@ -1056,7 +1051,7 @@ static int friend_decrypt(struct bt_mesh_subnet *sub, const u8_t *data, return 0; } } -#pragma GCC diagnostic pop + return -ENOENT; } @@ -1438,3 +1433,4 @@ void bt_mesh_net_init(void) k_work_init(&bt_mesh.local_work, bt_mesh_net_local); net_buf_slist_init(&bt_mesh.local_queue); } +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/net.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/net.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/net.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/net.h index 976da0053..1a7e3aa7d 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/net.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/net.h @@ -22,8 +22,8 @@ #include #include "atomic.h" -#include "mesh/mesh.h" -#include "mesh/glue.h" +#include "../include/mesh/mesh.h" +#include "../include/mesh/glue.h" /* How many hours in between updating IVU duration */ #define BT_MESH_IVU_MIN_HOURS 96 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/nodes.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/nodes.c similarity index 96% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/nodes.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/nodes.c index 127ef21e4..de41f40d0 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/nodes.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/nodes.c @@ -4,12 +4,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#if MYNEWT_VAL(BLE_MESH) + #define MESH_LOG_MODULE BLE_MESH_PROV_LOG #if MYNEWT_VAL(BLE_MESH_PROVISIONER) -#include "mesh/mesh.h" +#include "../include/mesh/mesh.h" #include "mesh_priv.h" #include "net.h" @@ -159,3 +161,4 @@ void bt_mesh_node_del(struct bt_mesh_node *node, bool store) } #endif +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/nodes.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/nodes.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/nodes.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/nodes.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/prov.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/prov.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov.c index fe92c0e34..f8f22fa7e 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/prov.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov.c @@ -6,14 +6,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#if MYNEWT_VAL(BLE_MESH) + #define MESH_LOG_MODULE BLE_MESH_PROV_LOG #if MYNEWT_VAL(BLE_MESH_PROV) #include -#include "mesh/mesh.h" +#include "../include/mesh/mesh.h" #include "mesh_priv.h" #include "crypto.h" @@ -2006,3 +2008,4 @@ void bt_mesh_prov_reset(void) } #endif /* MYNEWT_VAL(BLE_MESH_PROV) */ +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/prov.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov.h similarity index 85% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/prov.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov.h index 96e5a447c..c6866c9e2 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/prov.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov.h @@ -9,9 +9,9 @@ #ifndef __PROV_H__ #define __PROV_H__ -#include "os/os_mbuf.h" -#include "mesh/mesh.h" -#include "../src/ble_hs_conn_priv.h" +#include "nimble/porting/nimble/include/os/os_mbuf.h" +#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/src/ble_hs_conn_priv.h" int bt_mesh_pb_adv_open(const u8_t uuid[16], u16_t net_idx, u16_t addr, u8_t attention_duration); diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/proxy.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/proxy.c index 134a36dd6..6801791f1 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/proxy.c @@ -6,15 +6,17 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#if MYNEWT_VAL(BLE_MESH) + #define MESH_LOG_MODULE BLE_MESH_PROXY_LOG #if MYNEWT_VAL(BLE_MESH_PROXY) -#include "mesh/mesh.h" -#include "host/ble_att.h" -#include "services/gatt/ble_svc_gatt.h" -#include "../../host/src/ble_hs_priv.h" +#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/include/host/ble_att.h" +#include "nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h" +#include "nimble/nimble/host/src/ble_hs_priv.h" #include "mesh_priv.h" #include "adv.h" @@ -1497,3 +1499,4 @@ int bt_mesh_proxy_init(void) } #endif /* MYNEWT_VAL(BLE_MESH_PROXY) */ +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/proxy.h similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/proxy.h index 64338a0a3..e099947c9 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/proxy.h @@ -14,7 +14,7 @@ #define BT_MESH_PROXY_CONFIG 0x02 #define BT_MESH_PROXY_PROV 0x03 -#include "mesh/mesh.h" +#include "../include/mesh/mesh.h" int bt_mesh_proxy_send(uint16_t conn_handle, u8_t type, struct os_mbuf *msg); diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/settings.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/settings.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/settings.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/settings.c index 88d9b302e..2130e9e6c 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/settings.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/settings.c @@ -4,13 +4,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#if MYNEWT_VAL(BLE_MESH) + #define MESH_LOG_MODULE BLE_MESH_SETTINGS_LOG #if MYNEWT_VAL(BLE_MESH_SETTINGS) -#include "mesh/mesh.h" -#include "mesh/glue.h" +#include "../include/mesh/mesh.h" +#include "../include/mesh/glue.h" #include "net.h" #include "crypto.h" #include "transport.h" @@ -2081,3 +2083,4 @@ void bt_mesh_settings_init(void) } #endif /* MYNEWT_VAL(BLE_MESH_SETTINGS) */ +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/settings.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/settings.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/settings.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/settings.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/shell.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/shell.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/shell.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/shell.c index 91fbd9785..c19342764 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/shell.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/shell.c @@ -9,7 +9,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#if MYNEWT_VAL(BLE_MESH) #if MYNEWT_VAL(BLE_MESH_SHELL) @@ -2817,3 +2818,4 @@ void ble_mesh_shell_init(void) #endif } +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/shell.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/shell.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/shell.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/shell.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/transport.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/transport.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/transport.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/transport.c index caf1b4f12..c8e716a04 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/transport.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/transport.c @@ -6,13 +6,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#if MYNEWT_VAL(BLE_MESH) + #define MESH_LOG_MODULE BLE_MESH_TRANS_LOG #include #include -#include "mesh/mesh.h" +#include "../include/mesh/mesh.h" #include "mesh_priv.h" #include "crypto.h" @@ -1666,3 +1668,4 @@ int bt_mesh_app_key_get(const struct bt_mesh_subnet *subnet, u16_t app_idx, return 0; } +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/transport.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/transport.h similarity index 96% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/transport.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/transport.h index eff768e9f..227ba5922 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/transport.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/transport.h @@ -6,8 +6,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "syscfg/syscfg.h" -#include "mesh/mesh.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "../include/mesh/mesh.h" #define TRANS_SEQ_AUTH_NVAL 0xffffffffffffffff diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/syscfg.yml new file mode 100644 index 000000000..98632232b --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/syscfg.yml @@ -0,0 +1,661 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +syscfg.defs: + BLE_MESH_PROV: + description: > + Enable provisioning. It is automatically enabled whenever + BLE_MESH_PB_ADV or BLE_MESH_PB_GATT is set. + value: 1 + + BLE_MESH_PB_ADV: + description: > + Enable this option to allow the device to be provisioned over + the advertising bearer. + value: 1 + + BLE_MESH_PROVISIONER: + description: > + Enable this option to have support for provisioning remote devices. + value: 0 + restrictions: + - (BLE_MESH_PROV) + + BLE_MESH_NODE_COUNT: + description: > + This option specifies how many nodes each network can at most + save in the provisioning database. Range 1-4096 + value: 1 + + BLE_MESH_PROXY: + description: > + Enable proxy. This is automatically set whenever BLE_MESH_PB_GATT or + BLE_MESH_GATT_PROXY is set. + value: 0 + + BLE_MESH_PB_GATT: + description: > + Enable this option to allow the device to be provisioned over + the GATT bearer. + value: 1 + + BLE_MESH_GATT_PROXY: + description: > + This option enables support for the Mesh GATT Proxy Service, + i.e. the ability to act as a proxy between a Mesh GATT Client + and a Mesh network. + value: 1 + + BLE_MESH_NODE_ID_TIMEOUT: + description: > + This option determines for how long the local node advertises + using Node Identity. The given value is in seconds. The + specification limits this to 60 seconds, and implies that to + be the appropriate value as well, so just leaving this as the + default is the safest option. + value: 60 + + BLE_MESH_PROXY_FILTER_SIZE: + descryption: > + This option specifies how many Proxy Filter entries the local + node supports. + value: 1 + + BLE_MESH_SUBNET_COUNT: + description: > + This option specifies how many subnets a Mesh network can + participate in at the same time. + value: 1 + + BLE_MESH_APP_KEY_COUNT: + description: > + This option specifies how many application keys the device can + store per network. + value: 1 + + BLE_MESH_MODEL_KEY_COUNT: + description: > + This option specifies how many application keys each model can + at most be bound to. + value: 1 + + BLE_MESH_MODEL_GROUP_COUNT: + description: > + This option specifies how many group addresses each model can + at most be subscribed to. + value: 1 + + BLE_MESH_LABEL_COUNT: + description: > + This option specifies how many Label UUIDs can be stored. + value: 1 + + BLE_MESH_CRPL: + description: > + This options specifies the maximum capacity of the replay + protection list. This option is similar to the network message + cache size, but has a different purpose. + value: 10 + + BLE_MESH_ADV_TASK_PRIO: + description: > + Advertising task prio (FIXME) + type: task_priority + value: 9 + + BLE_MESH_MSG_CACHE_SIZE: + description: > + Number of messages that are cached for the network. This description + prevent unnecessary decryption operations and unnecessary + relays. This option is similar to the replay protection list, + but has a different purpose. + value: 10 + + BLE_MESH_ADV_BUF_COUNT: + description: > + Number of advertising buffers available. This should be chosen + based on what kind of features the local node shoule have. E.g. + a relay will perform better the more buffers it has. Another + thing to consider is outgoing segmented messages. There must + be at least three more advertising buffers than the maximum + supported outgoing segment count (BT_MESH_TX_SEG_MAX). + value: 6 + + BLE_MESH_IVU_DIVIDER: + description: > + When the IV Update state enters Normal operation or IV Update + in Progress, we need to keep track of how many hours has passed + in the state, since the specification requires us to remain in + the state at least for 96 hours (Update in Progress has an + additional upper limit of 144 hours). + + In order to fulfil the above requirement, even if the node might + be powered off once in a while, we need to store persistently + how many hours the node has been in the state. This doesn't + necessarily need to happen every hour (thanks to the flexible + duration range). The exact cadence will depend a lot on the + ways that the node will be used and what kind of power source it + has. + + Since there is no single optimal answer, this configuration + option allows specifying a divider, i.e. how many intervals + the 96 hour minimum gets split into. After each interval the + duration that the node has been in the current state gets + stored to flash. E.g. the default value of 4 means that the + state is saved every 24 hours (96 / 4). + value: 4 + + BLE_MESH_TX_SEG_MSG_COUNT: + description: > + Maximum number of simultaneous outgoing multi-segment and/or + reliable messages. + value: 4 + + BLE_MESH_RX_SEG_MSG_COUNT: + description: > + Maximum number of simultaneous incoming multi-segment and/or + reliable messages. + value: 2 + + BLE_MESH_RX_SDU_MAX: + description: > + Maximum incoming Upper Transport Access PDU length. This + determines also how many segments incoming segmented messages + can have. Each segment can contain 12 bytes, so this value should + be set to a multiple of 12 to avoid wasted memory. The minimum + requirement is 2 segments (24 bytes) whereas the maximum supported + by the Mesh specification is 32 segments (384 bytes). + value: 72 + + BLE_MESH_TX_SEG_MAX: + description: > + Maximum number of segments supported for outgoing messages. + This value should typically be fine-tuned based on what + models the local node supports, i.e. what's the largest + message payload that the node needs to be able to send. + This value affects memory and call stack consumption, which + is why the default is lower than the maximum that the + specification would allow (32 segments). + + The maximum outgoing SDU size is 12 times this number (out of + which 4 or 8 bytes is used for the Transport Layer MIC). For + example, 5 segments means the maximum SDU size is 60 bytes, + which leaves 56 bytes for application layer data using a + 4-byte MIC and 52 bytes using an 8-byte MIC. + + Be sure to specify a sufficient number of advertising buffers + when setting this option to a higher value. There must be at + least three more advertising buffers (BT_MESH_ADV_BUF_COUNT) + as there are outgoing segments. + value: 3 + + BLE_MESH_SEG_RETRANSMIT_ATTEMPTS: + description: > + Number of retransmit attempts (after the initial transmit) per segment + value: 4 + retrictions: 'BLE_MESH_SEG_RETRANSMIT_ATTEMPTS > 1' + + BLE_MESH_RELAY: + description: > + Support for acting as a Mesh Relay Node. + value: 0 + + BLE_MESH_LOW_POWER: + description: > + Enable this option to be able to act as a Low Power Node. + value: 0 + + BLE_MESH_LPN_ESTABLISHMENT: + description: > + Perform the Friendship establishment using low power, with + the help of a reduced scan duty cycle. The downside of this + is that the node may miss out on messages intended for it + until it has successfully set up Friendship with a Friend + node. + value: 1 + + BLE_MESH_LPN_AUTO: + description: > + Automatically enable LPN functionality once provisioned and start + looking for Friend nodes. If this option is disabled LPN mode + needs to be manually enabled by calling bt_mesh_lpn_set(true). + node. + value: 1 + + BLE_MESH_LPN_AUTO_TIMEOUT: + description: > + Time in seconds from the last received message, that the node + will wait before starting to look for Friend nodes. + value: 15 + + BLE_MESH_LPN_RETRY_TIMEOUT: + description: > + Time in seconds between Friend Requests, if a previous Friend + Request did not receive any acceptable Friend Offers. + value: 8 + + BLE_MESH_LPN_RSSI_FACTOR: + description: > + The contribution of the RSSI measured by the Friend node used + in Friend Offer Delay calculations. 0 = 1, 1 = 1.5, 2 = 2, 3 = 2.5. + value: 0 + + BLE_MESH_LPN_RECV_WIN_FACTOR: + description: > + The contribution of the supported Receive Window used in + Friend Offer Delay calculations. 0 = 1, 1 = 1.5, 2 = 2, 3 = 2.5. + value: 0 + + BLE_MESH_LPN_MIN_QUEUE_SIZE: + description: > + The MinQueueSizeLog field is defined as log_2(N), where N is + the minimum number of maximum size Lower Transport PDUs that + the Friend node can store in its Friend Queue. As an example, + MinQueueSizeLog value 1 gives N = 2, and value 7 gives N = 128. + value: 1 + + BLE_MESH_LPN_RECV_DELAY: + description: > + The ReceiveDelay is the time between the Low Power node + sending a request and listening for a response. This delay + allows the Friend node time to prepare the response. The value + is in units of milliseconds. + value: 100 + + BLE_MESH_LPN_POLL_TIMEOUT: + description: > + PollTimeout timer is used to measure time between two + consecutive requests sent by the Low Power node. If no + requests are received by the Friend node before the + PollTimeout timer expires, then the friendship is considered + terminated. The value is in units of 100 milliseconds, so e.g. + a value of 300 means 30 seconds. + value: 300 + + BLE_MESH_LPN_INIT_POLL_TIMEOUT: + description: > + The initial value of the PollTimeout timer when Friendship + gets established for the first time. After this the timeout + will gradually grow toward the actual PollTimeout, doubling + in value for each iteration. The value is in units of 100 + milliseconds, so e.g. a value of 300 means 3 seconds. + value: MYNEWT_VAL_BLE_MESH_LPN_POLL_TIMEOUT + + BLE_MESH_LPN_SCAN_LATENCY: + description: > + Latency in milliseconds that it takes to enable scanning. This + is in practice how much time in advance before the Receive Window + that scanning is requested to be enabled. + value: 10 + + BLE_MESH_LPN_GROUPS: + description: > + Maximum number of groups that the LPN can subscribe to. + value: 10 + + BLE_MESH_FRIEND: + description: > + Enable this option to be able to act as a Friend Node. + value: 0 + + BLE_MESH_FRIEND_RECV_WIN: + description: > + Receive Window in milliseconds supported by the Friend node. + value: 255 + + BLE_MESH_FRIEND_QUEUE_SIZE: + description: > + Minimum number of buffers available to be stored for each + local Friend Queue. + value: 16 + + BLE_MESH_FRIEND_SUB_LIST_SIZE: + description: > + Size of the Subscription List that can be supported by a + Friend node for a Low Power node. + value: 3 + + BLE_MESH_FRIEND_LPN_COUNT: + description: > + Number of Low Power Nodes the Friend can have a Friendship + with simultaneously. + value: 2 + + BLE_MESH_FRIEND_SEG_RX: + description: > + Number of incomplete segment lists that we track for each LPN + that we are Friends for. In other words, this determines how + many elements we can simultaneously be receiving segmented + messages from when the messages are going into the Friend queue. + value: 1 + + BLE_MESH_CFG_CLI: + description: > + Enable support for the configuration client model. + value: 0 + + BLE_MESH_HEALTH_CLI: + description: > + Enable support for the health client model. + value: 0 + + BLE_MESH_SHELL: + description: > + Activate shell module that provides Bluetooth Mesh commands to + the console. + value: 0 + + BLE_MESH_MODEL_EXTENSIONS: + description: > + Enable support for the model extension concept, allowing the Access + layer to know about Mesh model relationships. + value: 0 + + BLE_MESH_IV_UPDATE_TEST: + description: > + This option removes the 96 hour limit of the IV Update + Procedure and lets the state be changed at any time. + value: 0 + + BLE_MESH_TESTING: + description: > + This option enables testing API. + value: 0 + + BLE_MESH_DEV_UUID: + description: > + Device UUID + value: ((uint8_t[16]){0x11, 0x22, 0}) + + BLE_MESH_SHELL_MODELS: + description: > + Include implementation of some demo models. + value: 0 + + BLE_MESH_OOB_OUTPUT_ACTIONS: + description: > + Supported Output OOB Actions + BT_MESH_NO_OUTPUT = 0, + BT_MESH_BLINK = BIT(0) + BT_MESH_BEEP = BIT(1) + BT_MESH_VIBRATE = BIT(2) + BT_MESH_DISPLAY_NUMBER = BIT(3) + BT_MESH_DISPLAY_STRING = BIT(4) + value: ((BT_MESH_DISPLAY_NUMBER)) + + BLE_MESH_OOB_OUTPUT_SIZE: + description: > + Output OOB size + value: 4 + + BLE_MESH_OOB_INPUT_ACTIONS: + description: > + Supported Input OOB Actions + BT_MESH_NO_INPUT = 0, + BT_MESH_PUSH = BIT(0) + BT_MESH_TWIST = BIT(1) + BT_MESH_ENTER_NUMBER = BIT(2) + BT_MESH_ENTER_STRING = BIT(3) + value: ((BT_MESH_NO_INPUT)) + + BLE_MESH_OOB_INPUT_SIZE: + description: > + Input OOB size + value: 4 + + BLE_MESH_SETTINGS: + description: > + This option enables Mesh settings storage. + value: 1 + + BLE_MESH_STORE_TIMEOUT: + description: > + This value defines in seconds how soon any pending changes + are actually written into persistent storage (flash) after + a change occurs. + value: 2 + + BLE_MESH_SEQ_STORE_RATE: + description: > + This value defines how often the local sequence number gets + updated in persistent storage (i.e. flash). E.g. a value of 100 + means that the sequence number will be stored to flash on every + 100th increment. If the node sends messages very frequently a + higher value makes more sense, whereas if the node sends + infrequently a value as low as 0 (update storage for every + increment) can make sense. When the stack gets initialized it + will add this number to the last stored one, so that it starts + off with a value that's guaranteed to be larger than the last + one used before power off. + value: 128 + + BLE_MESH_RPL_STORE_TIMEOUT: + description: > + This value defines in seconds how soon the RPL gets written to + persistent storage after a change occurs. If the node receives + messages frequently it may make sense to have this set to a + large value, whereas if the RPL gets updated infrequently a + value as low as 0 (write immediately) may make sense. Note that + if the node operates a security sensitive use case, and there's + a risk of sudden power loss, it may be a security vulnerability + to set this value to anything else than 0 (a power loss before + writing to storage exposes the node to potential message + replay attacks). + value: 5 + + BLE_MESH_DEVICE_NAME: + description: > + This value defines BLE Mesh device/node name. + value: '"nimble-mesh-node"' + + BLE_MESH_SYSINIT_STAGE: + description: > + Primary sysinit stage for BLE mesh functionality. + value: 500 + + BLE_MESH_SYSINIT_STAGE_SHELL: + description: > + Secondary sysinit stage for BLE mesh functionality. + value: 1000 + + ### Log settings. + + BLE_MESH_LOG_MOD: + description: > + Numeric module ID to use for BLE Mesh log messages. + value: 9 + BLE_MESH_LOG_LVL: + description: > + Minimum level for the BLE Mesh log. + value: 1 + + BLE_MESH_ACCESS_LOG_MOD: + description: > + Numeric module ID to use for BLE Mesh Access-related log messages. + value: 10 + BLE_MESH_ACCESS_LOG_LVL: + description: > + Minimum level for the BLE Mesh Access-related log. + value: 1 + + BLE_MESH_ADV_LOG_MOD: + description: > + Numeric module ID to use for BLE Mesh advertising log messages. + value: 11 + BLE_MESH_ADV_LOG_LVL: + description: > + Minimum level for the BLE Mesh log. + value: 1 + + BLE_MESH_BEACON_LOG_MOD: + description: > + Numeric module ID to use for BLE Mesh Beacon-related log messages. + value: 12 + BLE_MESH_BEACON_LOG_LVL: + description: > + Minimum level for the BLE Mesh Beacon-related log. + value: 1 + + BLE_MESH_CRYPTO_LOG_MOD: + description: > + Numeric module ID to use for BLE Mesh cryptographic log messages. + value: 13 + BLE_MESH_CRYPTO_LOG_LVL: + description: > + Minimum level for the BLE Mesh cryptographic log. + value: 1 + + BLE_MESH_FRIEND_LOG_MOD: + description: > + Numeric module ID to use for BLE Mesh Friend log messages. + value: 14 + BLE_MESH_FRIEND_LOG_LVL: + description: > + Minimum level for the BLE Mesh Friend log. + value: 1 + + BLE_MESH_LOW_POWER_LOG_MOD: + description: > + Numeric module ID to use for BLE Mesh Low Power log messages. + value: 15 + BLE_MESH_LOW_POWER_LOG_LVL: + description: > + Minimum level for the BLE Mesh Low Power log. + value: 1 + + BLE_MESH_MODEL_LOG_MOD: + description: > + Numeric module ID to use for BLE Mesh Foundation Models log messages. + value: 16 + BLE_MESH_MODEL_LOG_LVL: + description: > + Minimum level for the BLE Mesh Foundation Models log. + value: 1 + + BLE_MESH_NET_LOG_MOD: + description: > + Numeric module ID to use for BLE Mesh Network layer log messages. + value: 17 + BLE_MESH_NET_LOG_LVL: + description: > + Minimum level for the BLE Mesh Network layer log. + value: 1 + + BLE_MESH_PROV_LOG_MOD: + description: > + Numeric module ID to use for BLE Mesh Provisioning log messages. + value: 18 + BLE_MESH_PROV_LOG_LVL: + description: > + Minimum level for the BLE Mesh Provisioning log. + value: 1 + + BLE_MESH_PROXY_LOG_MOD: + description: > + Numeric module ID to use for BLE Mesh Proxy protocol log messages. + value: 19 + BLE_MESH_PROXY_LOG_LVL: + description: > + Minimum level for the BLE Mesh Proxy protocol log. + value: 1 + + BLE_MESH_SETTINGS_LOG_MOD: + description: > + Numeric module ID to use for BLE Mesh persistent settings log messages. + value: 20 + BLE_MESH_SETTINGS_LOG_LVL: + description: > + Minimum level for the BLE Mesh persistent settings log. + value: 1 + + BLE_MESH_TRANS_LOG_MOD: + description: > + Numeric module ID to use for BLE Mesh Transport Layer log messages. + value: 21 + BLE_MESH_TRANS_LOG_LVL: + description: > + Minimum level for the BLE Mesh Transport Layer log. + value: 1 + +syscfg.logs: + BLE_MESH_LOG: + module: MYNEWT_VAL(BLE_MESH_LOG_MOD) + level: MYNEWT_VAL(BLE_MESH_LOG_LVL) + + BLE_MESH_ACCESS_LOG: + module: MYNEWT_VAL(BLE_MESH_ACCESS_LOG_MOD) + level: MYNEWT_VAL(BLE_MESH_ACCESS_LOG_LVL) + + BLE_MESH_ADV_LOG: + module: MYNEWT_VAL(BLE_MESH_ADV_LOG_MOD) + level: MYNEWT_VAL(BLE_MESH_ADV_LOG_LVL) + + BLE_MESH_BEACON_LOG: + module: MYNEWT_VAL(BLE_MESH_BEACON_LOG_MOD) + level: MYNEWT_VAL(BLE_MESH_BEACON_LOG_LVL) + + BLE_MESH_CRYPTO_LOG: + module: MYNEWT_VAL(BLE_MESH_CRYPTO_LOG_MOD) + level: MYNEWT_VAL(BLE_MESH_CRYPTO_LOG_LVL) + + BLE_MESH_FRIEND_LOG: + module: MYNEWT_VAL(BLE_MESH_FRIEND_LOG_MOD) + level: MYNEWT_VAL(BLE_MESH_FRIEND_LOG_LVL) + + BLE_MESH_LOW_POWER_LOG: + module: MYNEWT_VAL(BLE_MESH_LOW_POWER_LOG_MOD) + level: MYNEWT_VAL(BLE_MESH_LOW_POWER_LOG_LVL) + + BLE_MESH_MODEL_LOG: + module: MYNEWT_VAL(BLE_MESH_MODEL_LOG_MOD) + level: MYNEWT_VAL(BLE_MESH_MODEL_LOG_LVL) + + BLE_MESH_NET_LOG: + module: MYNEWT_VAL(BLE_MESH_NET_LOG_MOD) + level: MYNEWT_VAL(BLE_MESH_NET_LOG_LVL) + + BLE_MESH_PROV_LOG: + module: MYNEWT_VAL(BLE_MESH_PROV_LOG_MOD) + level: MYNEWT_VAL(BLE_MESH_PROV_LOG_LVL) + + BLE_MESH_PROXY_LOG: + module: MYNEWT_VAL(BLE_MESH_PROXY_LOG_MOD) + level: MYNEWT_VAL(BLE_MESH_PROXY_LOG_LVL) + + BLE_MESH_SETTINGS_LOG: + module: MYNEWT_VAL(BLE_MESH_SETTINGS_LOG_MOD) + level: MYNEWT_VAL(BLE_MESH_SETTINGS_LOG_LVL) + + BLE_MESH_TRANS_LOG: + module: MYNEWT_VAL(BLE_MESH_TRANS_LOG_MOD) + level: MYNEWT_VAL(BLE_MESH_TRANS_LOG_LVL) + +syscfg.vals.BLE_MESH_SHELL: + BLE_MESH_CFG_CLI: 1 + BLE_MESH_HEALTH_CLI: 1 + BLE_MESH_IV_UPDATE_TEST: 1 + +syscfg.vals.BLE_MESH_GATT_PROXY: + BLE_MESH_PROXY: 1 + +syscfg.vals.BLE_MESH_PB_GATT: + BLE_MESH_PROXY: 1 + BLE_MESH_PROV: 1 + +syscfg.vals.BLE_MESH_PB_ADV: + BLE_MESH_PROV: 1 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pkg.yml new file mode 100644 index 000000000..a063a0b63 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pkg.yml @@ -0,0 +1,55 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: nimble/host +pkg.description: Host side of the nimble Bluetooth Smart stack. +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - ble + - bluetooth + +pkg.deps: + - "@apache-mynewt-core/kernel/os" + - "@apache-mynewt-core/sys/log/modlog" + - "@apache-mynewt-core/util/mem" + - nimble + +pkg.deps.BLE_SM_LEGACY: + - "@apache-mynewt-core/crypto/tinycrypt" + +pkg.deps.BLE_SM_SC: + - "@apache-mynewt-core/crypto/tinycrypt" + +pkg.deps.BLE_MONITOR_RTT: + - "@apache-mynewt-core/hw/drivers/rtt" + +pkg.deps.BLE_MESH: + - nimble/host/mesh + +pkg.req_apis: + - ble_transport + - console + - stats + +pkg.init: + ble_hs_init: 'MYNEWT_VAL(BLE_HS_SYSINIT_STAGE)' + +pkg.down.BLE_HS_STOP_ON_SHUTDOWN: + ble_hs_shutdown: 200 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/README.txt b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/README.txt new file mode 100644 index 000000000..bb03b18ca --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/README.txt @@ -0,0 +1,8 @@ +This folder contains qualification tests results against BT SIG Profile Test +Suite. + +pts-FOO.txt files contain result for specific profiles or protocols. This +includes PTS version, test date, enabled tests, results etc. + +In addition to tests results 'tpg' folder constains Test Plang Generator +configuration files that can be imported by PTS for tests configuration. diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-gap.txt b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-gap.txt new file mode 100644 index 000000000..29ed2446e --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-gap.txt @@ -0,0 +1,367 @@ +PTS test results for GAP + +PTS version: 7.5.0 +Tested: 27-Sept-2019 + +Results: +PASS test passed +FAIL test failed +INC test is inconclusive +N/A test is disabled due to PICS setup + +------------------------------------------------------------------------------- +Test Name Result Notes +------------------------------------------------------------------------------- + +GAP/BROB/BCST/BV-01-C PASS advertise-configure legacy=1 connectable=0 scannable=0 +GAP/BROB/BCST/BV-02-C PASS advertise-configure legacy=1 connectable=0 scannable=0 + +GAP/BROB/BCST/BV-03-C PASS set irk= e.g: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:11 + Note: in PTS IXIT please set: + TSPX_iut_device_IRK_for_resolvable_privacy_address_generation_procedure=11000000000000000000000000000000 + set advertise-set-adv-data name= flags=4 + advertise-configure connectable=0 scannable=0 own_addr_type=rpa_pub +GAP/BROB/BCST/BV-04-C PASS TSPX_advertising_data=07086E696D626C65 + advertise-set-adv-data name=nimble + set addr_type=random addr=01:3e:56:f7:46:21 + advertise-configure connectable=0 scannable=0 own_addr_type=random +GAP/BROB/BCST/BV-05-C N/A +GAP/BROB/OBSV/BV-01-C PASS scan passive +GAP/BROB/OBSV/BV-02-C PASS scan +GAP/BROB/OBSV/BV-03-C PASS scan +GAP/BROB/OBSV/BV-04-C PASS connect peer_addr= + security-set-data bonding=1 + security-pair conn= + + +GAP/BROB/OBSV/BV-05-C PASS scan own_addr_type=rpa_pub +GAP/BROB/OBSV/BV-06-C PASS scan own_addr_type=rpa_pub +------------------------------------------------------------------------------- + +GAP/DISC/NONM/BV-01-C PASS advertise-configure connectable=0 legacy=1 adverdise=non +GAP/DISC/NONM/BV-02-C PASS advertise-configure connectable=0 + +GAP/DISC/LIMM/BV-01-C N/A +GAP/DISC/LIMM/BV-02-C N/A +GAP/DISC/LIMM/BV-03-C PASS advertise-configure legacy=1 connectable=0 + advertise-set-adv-data flags=5 + advertise-start duration= e.g.3000 +GAP/DISC/LIMM/BV-04-C PASS advertise-configure legacy=1 connectable=0 + advertise-set-adv-data flags=5 + advertising-start duration= +GAP/DISC/GENM/BV-01-C N/A +GAP/DISC/GENM/BV-02-C N/A +GAP/DISC/GENM/BV-03-C PASS advertise-configure legacy=1 connectable=0 + advertise-set-adv-data flags=6 + advertise-start +GAP/DISC/GENM/BV-04-C PASS advertise-configure legacy=1 connectable=0 + advertise-set-adv-data flags=6 + advertising-start + +GAP/DISC/LIMP/BV-01-C PASS scan limited=1 nodups=1 +GAP/DISC/LIMP/BV-02-C PASS scan limited=1 nodups=1 +GAP/DISC/LIMP/BV-03-C PASS scan limited=1 nodups=1 +GAP/DISC/LIMP/BV-04-C PASS scan limited=1 nodups=1 +GAP/DISC/LIMP/BV-05-C PASS scan limited=1 nodups=1 + +GAP/DISC/GENP/BV-01-C PASS scan nodups=1 +GAP/DISC/GENP/BV-02-C PASS scan nodups=1 +GAP/DISC/GENP/BV-03-C PASS scan nodups=1 + +GAP/DISC/GENP/BV-04-C PASS scan nodups=1 + +GAP/DISC/GENP/BV-05-C PASS scan nodups=1 + +GAP/DISC/RPA/BV-01-C N/A scan nodups=1 +------------------------------------------------------------------------------- + +GAP/IDLE/GIN/BV-01-C N/A +GAP/IDLE/GIN/BV-02-C N/A +GAP/IDLE/NAMP/BV-01-C PASS advertise-configure connectable=1 legacy=1 + advertising-start + gatt-discover-full conn= + gatt-show + + gatt-read conn= uuid=0x2a00 start= end= + disconnect conn= +GAP/IDLE/NAMP/BV-02-C PASS + advertise-configure connectable=1 legacy=1 + advertising-start +GAP/IDLE/DED/BV-01-C N/A +GAP/IDLE/DED/BV-02-C N/A +------------------------------------------------------------------------------- + +GAP/CONN/NCON/BV-01-C PASS advertise-configure connectable=0 legacy=1 + advertising-start +GAP/CONN/NCON/BV-02-C PASS advertise-configure connectable=0 legacy=1 + advertise-set-adv-data flags=6 + advertise-start +GAP/CONN/NCON/BV-03-C PASS advertise-configure connectable=0 legacy=1 + advertise-set-adv-data flags=5 + advertise-start + +GAP/CONN/DCON/BV-01-C PASS advertise-configure connectable=0 directed=1 peer_addr= + advertise-start +GAP/CONN/DCON/BV-02-C N/A +GAP/CONN/DCON/BV-03-C N/A + +GAP/CONN/UCON/BV-01-C PASS advertise-configure connectable=1 legacy=1 + advertise-set-adv-data flags=4 + advertise-start +GAP/CONN/UCON/BV-02_C PASS advertise-configure connectable=1 legacy=1 + advertise-set-adv-data flags=5 + advertise-start +GAP/CONN/UCON/BV-03_C PASS adbertise-configure connectable=1 legacy=1 + advertise-set-adv-data flags=6 +GAP/CONN/UCON/BV-04_C N/A +GAP/CONN/UCON/BV-05_C N/A +GAP/CONN/UCON/BV-06_C N/A + +GAP/CONN/ACEP/BV-01-C PASS white-list addr_type=public addr= + connect + disconnect conn= +GAP/CONN/ACEP/BV-02-C N/A + +GAP/CONN/GCEP/BV-01-C PASS connect peer_addr= + disconnect conn= +GAP/CONN/GCEP/BV-02-C PASS connect peer_addr= +GAP/CONN/GCEP/BV-03-C PASS set irk= + connect peer_addr= own_addr_type=rpa_pub + security-set-data bonding=1 our_key_dist=7 their_key_dist=7 + security-pair conn= + connect peer_addr= + disconnect conn=1 +GAP/CONN/GCEP/BV-04-C N/A +GAP/CONN/SCEP/BV-01-C PASS white-list addr_type=public addr= + connect + disconnect conn= +GAP/CONN/SCEP/BV-02-C INC +GAP/CONN/DCEP/BV-01-C PASS connect peer_addr= + disconnect conn= +GAP/CONN/DCEP/BV-02-C INC +GAP/CONN/DCEP/BV-03-C PASS connect peer_addr= + disconnect conn= +GAP/CONN/DCEP/BV-04-C PASS connect peer_addr= + disconnect conn= + +GAP/CONN/CPUP/BV-01-C PASS advertise-start + conn-update-params conn= +GAP/CONN/CPUP/BV-02-C PASS advertise-start + conn-update-params conn= +GAP/CONN/CPUP/BV-03-C PASS advertise-start + conn-update-params conn= +GAP/CONN/CPUP/BV-04-C PASS connect peer_addr= + disconnect conn= +GAP/CONN/CPUP/BV-05-C PASS connect peer_addr= + disconnect conn= +GAP/CONN/CPUP/BV-06-C PASS conect peer_addr= + conn-update-params conn= eg.latency=20 + disconnect conn= +GAP/CONN/CPUP/BV-08-C PASS advertise-configure legacy=1 connectable=1 + advertise-set-data name= + advertise-start + +GAP/CONN/TERM/BV-01-C PASS connect peer_addr= + disconnect conn= +GAP/CONN/PRDA/BV-01-C N/A +GAP/CONN/PRDA/BV-02-C N/A +------------------------------------------------------------------------------- +GAP/BOND/NBON/BV-01-C PASS security-set-data bonding=0 + connect peer_addr= + + connect peer_addr= + +GAP/BOND/NBON/BV-02-C PASS security-set-data bonding=0 + connect peer_addr= + security-pair conn= + + connect peer_addr= + security-pair conn= + +GAP/BOND/NBON/BV-03-C PASS security-set-data bonding=0 + advertise-configure legacy=1 connectable=1 + advertise-set-data name= + advertise-start + + +GAP/BOND/BON/BV-01-C PASS security-set-data bonding=1 sc=1 our_key_dist=7 their_key_dist=7 + advertise-configure legacy=1 connectable=1 + advertise-start + security-start conn= + + advertise-start + +GAP/BOND/BON/BV-02-C PASS security-set-data bonding=1 + connect peer_addr= + security-pair conn= + + connect peer_addr= + seccurity-pair conn= + +GAP/BOND/BON/BV-03-C PASS security-set-sm-data bonding=1 our_key_dist=7 their_key_dist=7 + advertise-configure legacy=1 connectable=1 + advertise-start + + advertise-start + +GAP/BOND/BON/BV-04-C PASS security-set-data bonding=1 + connect-peer_addr= + disconnect conn= + connect peer_addr= + security-pair conn= + disconnect conn= +------------------------------------------------------------------------------- + +GAP/SEC/AUT/BV-11-C PASS security-set-data io_capabilities=1 sc=1 + advertise-configure legacy=1 connectable=1 + advertising-start + Note: in PTS enter handle for characteristics + value which requires encryption for read (gatt-show-local) + auth-passkey conn= action=3 key=123456 + Note: enter '123456' passkey in PTS +GAP/SEC/AUT/BV-12-C PASS security-set-data io_capabilities=1 bonding=1 mitm_flag=1 sc=1 our_key_dist=7 their_key_dist=7 + connect peer_addr= + gatt-show-local + Note: in PTS enter handle for characteristics + value which requires encryption for read + auth-passkey conn= action=3 key=123456 + Note: enter '123456' passkey in PTS +GAP/SEC/AUT/BV-13-C PASS Note: in PTS confirm that IUT supports GATT Server + security-set-data io_capabilities=1 bonding=1 mitm_flag=1 sc=1 our_key_dist=7 their_key_dist=7 + connect peer_addr= + gatt-show-local + Note: in PTS enter handle for characteristics + value which requires authenticated pairing for read + auth-passkey conn= action=3 key=123456 + Note: enter '123456' passkey in PTS +GAP/SEC/AUT/BV-14-C PASS security-set-data io_capabilities=1 + advertise-configure legacy=1 connectable=1 + advertise-start + gatt-show-local + Note: in PTS enter handle for characteristics + value which requires authenticated pairing for read + auth-passkey conn= action=3 key=123456 + Note: enter '123456' passkey in PTS +GAP/SEC/AUT/BV-15-C N/A security-set-data bonding=1 io_capabilities=4 mitm_flag=1 sc=1 our_key_dist=7 their_key_dist=7 + advertise-configure legacy=1 connectable=1 + advertise-start + auth-passkey conn= action=2 key= + advertise-start + gatt-show-local + Note: in PTS enter handle for characteristics + value which requires authenticated pairing for read +GAP/SEC/AUT/BV-16-C N/A security-set-data io_capabilities=1 bonding=1 mitm_flag=1 sc=1 our_key_dist=7 their_key_dist=7 + connect peer_addr= + auth-passkey conn= action=3 key=123456 + Note: enter '123456' passkey in PTS + connect peer_addr= + gatt-show-local + Note: in PTS enter handle for characteristics + value which requires authenticated pairing for read +GAP/SEC/AUT/BV-17-C N/A +GAP/SEC/AUT/BV-18-C N/A +GAP/SEC/AUT/BV-19-C N/A +GAP/SEC/AUT/BV-20-C N/A +GAP/SEC/AUT/BV-21-C N/A +GAP/SEC/AUT/BV-22-C N/A +GAP/SEC/AUT/BV-23-C N/A +GAP/SEC/AUT/BV-24-C N/A + +GAP/SEC/CSIGN/BV-01-C N/A +GAP/SEC/CSIGN/BV-02-C N/A + +GAP/SEC/CSIGN/BI-01-C N/A +GAP/SEC/CSIGN/BI-02-C N/A +GAP/SEC/CSIGN/BI-03-C N/A +GAP/SEC/CSIGN/BI-04-C N/A +------------------------------------------------------------------------------- + +GAP/PRIV/CONN/BV-01-C N/A +GAP/PRIV/CONN/BV-02-C N/A +GAP/PRIV/CONN/BV-03-C N/A +GAP/PRIV/CONN/BV-04-C INC +GAP/PRIV/CONN/BV-05-C N/A +GAP/PRIV/CONN/BV-06-C N/A +GAP/PRIV/CONN/BV-07-C N/A +GAP/PRIV/CONN/BV-08-C N/A +GAP/PRIV/CONN/BV-09-C N/A +GAP/PRIV/CONN/BV-10-C N/A +GAP/PRIV/CONN/BV-11-C N/A +------------------------------------------------------------------------------- + +GAP/ADV/BV-01-C PASS advertise-set-adv_data uuid16=0x1802 + advertise-start + advertise-stop +GAP/ADV/BV-02-C PASS advertise-set-adv_data name= + advertise-start + advertise-stop +GAP/ADV/BV-03-C PASS advertise-set-adv_data flags=6 + advertise-start + advertise-stop +GAP/ADV/BV-04-C PASS advertise-set-adv_data mfg_data=ff:ff + advertise-start + advertise-stop +GAP/ADV/BV-05-C PASS advertise-set-adv_data tx_pwr_lvl=10 + advertise-start + advertise-stop +GAP/ADV/BV-08-C N/A +GAP/ADV/BV-09-C N/A +GAP/ADV/BV-10-C PASS advetrise-set-adv_data service_data_uuid16=18:02:ff:ff + advertise-start + advertise-stop +GAP/ADV/BV-11-C PASS advertise-set -dv_data appearance=12 + advertise-start + advertise-stop +GAP/ADV/BV-12-C N/A +GAP/ADV/BV-13-C N/A +GAP/ADV/BV-14-C N/A +GAP/ADV/BV-15-C N/A +GAP/ADV/BV-16-C N/A +GAP/ADV/BV-17-C PASS In PTS: TSPX_URI= + set-adv-data uri= + advertise-start + advertise-stop +------------------------------------------------------------------------------- + +GAP/GAT/BV-01-C PASS + advertising-start + + connect peer_addr= +GAP/GAT/BV-02-C N/A +GAP/GAT/BV-03-C N/A +GAP/GAT/BV-04-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GAP/GAT/BV-05-C N/A +GAP/GAT/BV-06-C N/A +GAP/GAT/BV-07-C N/A +GAP/GAT/BV-08-C N/A +---------------------------------------------------------------------------- + +GAP/DM/NCON/BV-01-C N/A +GAP/DM/CON/BV-01-C N/A +GAP/DM/NBON/BV-01-C N/A +GAP/DM/BON/BV-01-C N/A +GAP/DM/GIN/BV-01-C N/A +GAP/DM/LIN/BV-01-C N/A +GAP/DM/NAD/BV-01-C N/A +GAP/DM/NAD/BV-02-C N/A +GAP/DM/LEP/BV-01-C N/A +GAP/DM/LEP/BV-02-C N/A +GAP/DM/LEP/BV-04-C N/A +GAP/DM/LEP/BV-05-C N/A +GAP/DM/LEP/BV-06-C N/A +GAP/DM/LEP/BV-07-C N/A +GAP/DM/LEP/BV-08-C N/A +GAP/DM/LEP/BV-09-C N/A +GAP/DM/LEP/BV-10-C N/A +GAP/DM/LEP/BV-11-C N/A +------------------------------------------------------------------------------- + +GAP/MOD/NDIS/BV-01-C N/A +GAP/MOD/LDIS/BV-01-C N/A +GAP/MOD/LDIS/BV-02-C N/A +GAP/MOD/LDIS/BV-03-C N/A +GAP/MOD/GDIS/BV-01-C N/A +GAP/MOD/GDIS/BV-02-C N/A +GAP/MOD/NCON/BV-01-C N/A +GAP/MOD/CON/BV-01-C N/A \ No newline at end of file diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-gatt.txt b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-gatt.txt new file mode 100644 index 000000000..74c0a2e01 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-gatt.txt @@ -0,0 +1,508 @@ +PTS test results for GATT + +PTS version: 7.5.0 +Tested: 27-Sept-2019 + +Results: +PASS test passed +FAIL test failed +INC test is inconclusive +N/A test is disabled due to PICS setup + +------------------------------------------------------------------------------- +Test Name Result Notes +------------------------------------------------------------------------------- +GATT/CL/GAC/BV-01-C PASS connect peer_addr= + gatt-exchanche-mtu conn= + gatt-write conn= long=1 attr= value= + disconnect conn= +------------------------------------------------------------------------------- + +GATT/CL/GAD/BV-01-C PASS connect peer_addr= + gatt-discover-service conn= + gatt-show + + disconnect conn= + +GATT/CL/GAD/BV-02-C PASS connect peer_addr= + gatt-discover-service conn= uuid= + gatt-show + + disconnect conn= + +GATT/CL/GAD/BV-03-C PASS connect peer_addr= + gatt-find-included-services conn= start=1 end=0xffff + + disconnect conn= + +GATT/CL/GAD/BV-04-C PASS connect peer_addr= + gatt-discover-service conn= uuid= + gatt-discover-characteristic conn= start= end= + gatt-show + + disconnect conn= + +GATT/CL/GAD/BV-05-C PASS connect peer_addr= + gatt-discover-service conn= + gatt-discover-characteristic conn= uuid= start= end= + gatt-show + + disconnect conn= + +GATT/CL/GAD/BV-06-C PASS connect peer_addr= + gatt-discover-service conn= + gatt-discover-characteristic conn= start= end= + gatt-discover-descriptor conn= start= end= + + disconnect conn= + +GATT/CL/GAD/BV-07-C N/A +GATT/CL/GAD/BV-08-C N/A +------------------------------------------------------------------------------- + +GATT/CL/GAR/BV-01-C PASS connect peer_addr= + gatt-read conn= attr= + + disconnect conn= +GATT/CL/GAR/BI-01-C PASS connect peer_addr= + gatt-read conn= attr= + + disconnect conn= +GATT/CL/GAR/BI-02-C PASS connect peer_addr= + gatt-read conn= attr= + + disconnect conn= +GATT/CL/GAR/BI-03-C N/A + +GATT/CL/GAR/BI-04-C PASS connect peer_addr= + gatt-read conn= attr= + disconnect conn= + +GATT/CL/GAR/BI-05-C PASS connect peer_addr= + gatt-read conn= attr= + + disconnect conn= +GATT/CL/GAR/BV-03-C PASS connect peer_addr= + gatt-read conn= uuid= start=1 end=0xffff + + + disconnect conn= +GATT/CL/GAR/BI-06-C PASS connect peer_addr= + gatt-read conn= uuid= start= end= + disconnect conn= + +GATT/CL/GAR/BI-07-C PASS connect peer_addr= + gatt-read conn= uuid= start= end= + disconnect conn= + +GATT/CL/GAR/BI-09-C N/A +GATT/CL/GAR/BI-10-C PASS connect peer_addr= + gatt-read conn= uuid= start= end= + disconnect conn= + +GATT/CL/GAR/BI-11-C PASS connect perr_addr= + gatt-read conn= start= end= + disconnect conn= + +GATT/CL/GAR/BV-04-C PASS connect peer_addr= + gatt-read conn= long=1 attr= + + + disconnect conn= +GATT/CL/GAR/BI-12-C PASS connect peer_addr= + gatt-read conn= long=1 attr= + + disconnect conn= +GATT/CL/GAR/BI-13-C PASS connect peer_addr= + gatt-read conn= long=1 attr= offset= + + disconnect conn= +GATT/CL/GAR/BI-14-C PASS connect peer_addr= + gatt-read conn= long=1 attr= + disconnect conn= + +GATT/CL/GAR/BI-15-C N/A + +GATT/CL/GAR/BI-16-C PASS connect peer_addr= + gatt-read conn= long=1 attr= + disconnect conn= + +GATT/CL/GAR/BI-17-C PASS connect peer_addr= + gatt-read conn= long=1 attr= + + disconnect conn= +GATT/CL/GAR/BV-05-C PASS connect peer_addr= + gatt-read conn= attr= attr= + disconnect conn= +GATT/CL/GAR/BI-18-C PASS connect peer_addr= + gatt-read conn= attr= attr= + + disconnect conn= +GATT/CL/GAR/BI-19-C PASS connect peer_addr= + gatt-read conn= attr= attr= + disconnect conn= + +GATT/CL/GAR/BI-20-C N/A + +GATT/CL/GAR/BI-21-C PASS connect peer_addr= + gatt-read conn= attr= attr= + disconnect conn= + +GATT/CL/GAR/BI-22-C PASS connect peer_addr= + gatt-read conn= attr= attr= + + disconnect conn= +GATT/CL/GAR/BV-06-C PASS connect peer_addr= + gatt-read conn= attr= + + disconnect conn= +GATT/CL/GAR/BV-07-C PASS connect peer_addr= + gatt-read conn= long=1 attr= + + + disconnect conn= +GATT/CL/GAR/BI-34-C N/A +GATT/CL/GAR/BI-35-C PASS connect peer_addr= + gatt-read conn= long=1 attr= + + disconnect conn= +------------------------------------------------------------------------------- + +GATT/CL/GAW/BV-01-C PASS connect peer_addr= + gatt-write no_rsp=1 conn= attr= value= + disconnect conn= +GATT/CL/GAW/BV-02-C N/A + +GATT/CL/GAW/BV-03-C PASS connect peer_addr= + gatt-write conn= attr= value= + disconnect conn= +GATT/CL/GAW/BI-02-C PASS connect peer_addr= + gatt-write conn= attr= value= + disconnect conn= +GATT/CL/GAW/BI-03-C PASS connect peer_addr= + gatt-write conn= attr= value= + disconnect conn= +GATT/CL/GAW/BI-04-C N/A + +GATT/CL/GAW/BI-05-C PASS connect peer_addr= + gatt-write conn= attr= value= + disconnect conn= +GATT/CL/GAW/BI-06-C PASS connect peer_addr= + gatt-write conn= attr= value= + disconnect conn= +GATT/CL/GAW/BV-05-C PASS connect peer_addr= + gatt-write long=1 conn= attr= value= + disconnect conn= +GATT/CL/GAW/BI-07-C PASS connect peer_addr= + gatt-write long=1 conn= attr= value= + disocnnect conn= +GATT/CL/GAW/BI-08-C PASS connect peer_addr= + gatt-write long=1 conn= attr= value= + diconnect conn= +GATT/CL/GAW/BI-09-C PASS connect peer_addr= + gatt-write long=1 conn= attr= value= offset= + diconnect conn=1 +GATT/CL/GAW/BI-11-C N/A + +GATT/CL/GAW/BI-12-C PASS connect peer_addr= + gatt-write long=1 conn= attr= value= + disconnect conn= +GATT/CL/GAW/BI-13-C PASS connect peer_addr= + gatt-write long=1 conn= attr= value= + diconnect conn= +GATT/CL/GAW/BV-06-C PASS connect peer_addr= + gatt-write long=1 conn= attr= value= + +GAAT/CL/GAW/BV-08-C PASS connect peer_addr= + gat-write conn= attr= value= + +GATT/CL/GAW/BV-09-C PASS connect peer_addr= + gatt-write long=1 conn= attr= value= + +GATT/CL/GAW/BI-32-C PASS connect peer_addr= + gatt-write conn= attr= value= attr= value= + disconnect conn= +GATT/CL/GAW/BI-33-C PASS connect peer_addr= + gatt-write conn= attr= value= + disconnect conn= +GATT/CL/GAW/BI-34-C PASS connect peer_addr= + gatt-write long=1 conn= attr= value= + disconnect conn= + +------------------------------------------------------------------------------- + +GATT/CL/GAN/BV-01-C PASS connect peer_addr= + gatt-write conn= attr= value=01:00 + Note: verify that the notification was received + disconnect conn= +------------------------------------------------------------------------------- + +GATT/CL/GAI/BV-01-C PASS connect peer_addr= + gatt-write conn= attr= value=01:00 + Note: verify that the notification was received + disconnect conn= +------------------------------------------------------------------------------- + +GATT/CL/GAS/BV-01-C PASS connect peer_addr= + disconnect conn= +------------------------------------------------------------------------------- + +GATT/CL/GAT/BV-01-C PASS connect peer_addr= + gatt-read conn= attr= +GATT/CL/GAT/BV-02-C PASS connect peer_addr= + gatt-write conn= attr= value= +------------------------------------------------------------------------------- + +GATT/CL/GPA/BV-01-C N/A +GATT/CL/GPA/BV-02-C N/A +GATT/CL/GPA/BV-03-C N/A +GATT/CL/GPA/BV-04-C N/A +GATT/CL/GPA/BV-05-C N/A +GATT/CL/GPA/BV-06-C N/A +GATT/CL/GPA/BV-07-C N/A +GATT/CL/GPA/BV-08-C N/A +GATT/CL/GPA/BV-11-C N/A +GATT/CL/GPA/BV-12-C N/A +------------------------------------------------------------------------------- + +GATT/SR/GAC/BV-01-C PASS set mtu=25 + advertise-configure connectable=1 legacy=1 + advertise-start + advertise-start +------------------------------------------------------------------------------- + +GATT/SR/GAD/BV-01-C PASS advertise-configure connectable=1 legacy=1 + advertise-start + gatt-show-local + +GATT/SR/GAD/BV-02-C PASS advertise-configure connectable=1 legacy=1 + advertise-start + gatt-show-local + +GATT/SR/GAD/BV-03-C PASS advertise-configure connectable=1 legacy=1 + advertise-start + gatt-show-local + +GATT/SR/GAD/BV-04-C PASS advertise-configure connectable=1 legacy=1 + advertise-start + +GATT/SR/GAD/BV-05-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAD/BV-06-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAD/BV-07-C N/A +GATT/SR/GAD/BV-08-C N/A +------------------------------------------------------------------------------- + +GATT/SR/GAR/BV-01-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAR/BI-01-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAR/BI-02-C PASS advertise-configure connectable=1 legacy=1 + advertise-start + +GATT/SR/GAR/BI-03-C N/A +GATT/SR/GAR/BI-04-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAR/BI-05-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAR/BV-03-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAR/BI-06-C PASS advertise-configure connectable=1 legacy=1 + advertise-start + gatt-show-local + + +GATT/SR/GAR/BI-07-C PASS advertise-configure connectable=1 legacy=1 + advertise-start + +GATT/SR/GAR/BI-08-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAR/BI-09-C N/A +GATT/SR/GAR/BI-10-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAR/BI-11-C PASS advertise-configure connectable=1 legacy=1 + advertise-start + +GATT/SR/GAR/BV-04-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAR/BI-12-C PASS advertise-configure connectable=1 legacy=1 + advertise-start + +GATT/SR/GAR/BI-13-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAR/BI-14-C PASS advertise-configure connectable=1 legacy=1 + advertise-start + +GATT/SR/GAR/BI-15-C N/A +GATT/SR/GAR/BI-16-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAR/BI-17-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAR/BV-05-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAR/BI-18-C PASS advertise-configure connectable=1 legacy=1 + advertise-start + +GATT/SR/GAR/BI-19-C PASS advertise-configure connectable=1 legacy=1 + advertise-start + +GATT/SR/GAR/BI-20-C N/A +GATT/SR/GAR/BI-21-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAR/BI-22-C PASS advertise-configure connectable=1 legacy=1 + advertise-startt +GATT/SR/GAR/BV-06-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAR/BI-23-C N/A +GATT/SR/GAR/BI-24-C N/A +GATT/SR/GAR/BI-25-C N/A +GATT/SR/GAR/BI-26-C N/A +GATT/SR/GAR/BI-27-C N/A +GATT/SR/GAR/BV-07-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAR/BV-08-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAR/BI-28-C N/A +GATT/SR/GAR/BI-29-C N/A +GATT/SR/GAR/BI-30-C N/A +GATT/SR/GAR/BI-31-C N/A +GATT/SR/GAR/BI-32-C N/A +GATT/SR/GAR/BI-33-C N/A +GATT/SR/GAR/BI-34-C N/A +GATT/SR/GAR/BI-35-C N/A +------------------------------------------------------------------------------- + +GATT/SR/GAW/BV-01-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAW/BV-02-C N/A +GATT/SR/GAW/BI-01-C N/A +GATT/SR/GAW/BV-03-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAW/BI-02-C PASS advertise-configure connectable=1 legacy=1 + advertise-start + +GATT/SR/GAW/BI-03-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAW/BI-04-C N/A +GATT/SR/GAW/BI-05-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAW/BI-06-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAW/BV-05-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAW/BI-07-C PASS advertise-configure connectable=1 legacy=1 + advertise-start + +GATT/SR/GAW/BI-08-C PASS advertise-configure connectable=1 legacy=1 + advertise-start + +GATT/SR/GAW/BI-09-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAW/BI-11-C N/A +GATT/SR/GAW/BI-12-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAW/BI-13-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAW/BV-06-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAW/BV-10-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAW/BI-14-C PASS advertise-configure connectable=1 legacy=1 + advertise-start + +GATT/SR/GAW/BI-15-C PASS advertise-configure connectable=1 legacy=1 + advertise-start + +GATT/SR/GAW/BI-17-C N/A +GATT/SR/GAW/BI-18-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAW/BI-19-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAW/BV-11-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAW/BV-07-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAW/BV-08-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAW/BI-20-C PASS advertise-configure connectable=1 legacy=1 + advertise-start + +GATT/SR/GAW/BI-21-C PASS advertise-configure connectable=1 legacy=1 + advertise-start + +GATT/SR/GAW/BI-22-C N/A +GATT/SR/GAW/BI-23-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAW/BI-24-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAW/BV-09-C PASS advertise-configure connectable=1 legacy=1q + advertise-start +GATT/SR/GAW/BI-25-C PASS advertise-configure connectable=1 legacy=1 + advertise-start + +GATT/SR/GAW/BI-26-C PASS advertise-configure connectable=1 legacy=1 + advertise-start + +GATT/SR/GAW/BI-27-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAW/BI-29-C N/A +GATT/SR/GAW/BI-30-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAW/BI-31-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAW/BI-32-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAW/BI-33-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAW/BI-34-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/GAW/BI-35-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +------------------------------------------------------------------------------ + +GATT/SR/GAN/BV-01-C PASS advertise-configure connectable=1 legacy=1 + advertise-start + gatt-notify attr= +------------------------------------------------------------------------------ + +GATT/SR/GAI/BV-01-C PASS advertise-configure connectable=1 legacy=1 + advertise-start + gatt-notify attr= +------------------------------------------------------------------------------- + +GATT/SR/GAS/BV-01-C PASS Note: set TSPX_security_enabled to TRUE + security-set-data bonding=1 our_key_dist=7 their_key_dist=7 + advertise-configure connectable=1 legacy=1 + advertise-start + + gatt-service-changed start=1 end=0xffff + advertise-start + security-start conn= +------------------------------------------------------------------------------- + +GATT/SR/GAT/BV-01-C PASS advertise-start + gatt-notify attr=0x0008 +------------------------------------------------------------------------------ + +GATT/SR/GPA/BV-01-C N/A +GATT/SR/GPA/BV-02-C N/A +GATT/SR/GPA/BV-03-C N/A +GATT/SR/GPA/BV-04-C N/A +GATT/SR/GPA/BV-05-C N/A +GATT/SR/GPA/BV-06-C N/A +GATT/SR/GPA/BV-07-C N/A +GATT/SR/GPA/BV-08-C N/A +GATT/SR/GPA/BV-11-C N/A +GATT/SR/GPA/BV-12-C N/A +------------------------------------------------------------------------------- + +GATT/SR/UNS/BI-01-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +GATT/SR/UNS/BI-02-C PASS advertise-configure connectable=1 legacy=1 + advertise-start + +-------------------------------------------------------------------------------- + +GATT/SR/GPM/BV-01-C N/A + diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-l2cap.txt b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-l2cap.txt new file mode 100644 index 000000000..c09add916 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-l2cap.txt @@ -0,0 +1,304 @@ +PTS test results for L2CAP + +PTS version: 7.5.0 +Tested: 07-Oct-2019 + +syscfg.vals: + BLE_EXT_ADV: 1 + BLE_PUBLIC_DEV_ADDR: "((uint8_t[6]){0x01, 0xff, 0xff, 0xc0, 0xde, 0xc0})" + BLE_SM_LEGACY: 1 + BLE_SM_SC: 1 + BLE_L2CAP_COC_MAX_NUM: 5 + BLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL: 9 + BLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL: 30 + BLE_SVC_GAP_PPCP_SUPERVISION_TMO: 2000 + CONSOLE_HISTORY_SIZE: 10 + +Results: +PASS test passed +FAIL test failed +INC test is inconclusive +N/A test is disabled due to PICS setup + +------------------------------------------------------------------------------- +Test Name Result Notes +------------------------------------------------------------------------------- + +L2CAP/COS/CED/BV-01-C N/A +L2CAP/COS/CED/BV-03-C N/A +L2CAP/COS/CED/BV-04-C N/A +L2CAP/COS/CED/BV-05-C N/A +L2CAP/COS/CED/BV-07-C N/A +L2CAP/COS/CED/BV-08-C N/A +L2CAP/COS/CED/BV-09-C N/A +L2CAP/COS/CED/BV-10-C N/A +L2CAP/COS/CED/BV-11-C N/A +L2CAP/COS/CED/BI-01-C N/A +------------------------------------------------------------------------------- + +L2CAP/COS/CFD/BV-01-C N/A +L2CAP/COS/CFD/BV-02-C N/A +L2CAP/COS/CFD/BV-03-C N/A +L2CAP/COS/CFD/BV-08-C N/A +L2CAP/COS/CFD/BV-09-C N/A +L2CAP/COS/CFD/BV-10-C N/A +L2CAP/COS/CFD/BV-11-C N/A +L2CAP/COS/CFD/BV-12-C N/A +L2CAP/COS/CFD/BV-13-C N/A +------------------------------------------------------------------------------- + +L2CAP/COS/IEX/BV-01-C N/A +L2CAP/COS/IEX/BV-02-C N/A +------------------------------------------------------------------------------- + +L2CAP/COS/ECH/BV-01-C N/A +L2CAP/COS/ECH/BV-02-C N/A +------------------------------------------------------------------------------- + +L2CAP/COS/CFC/BV-01-C PASS advertise-configure connectable=1 legacy=1 + advertise-set-adv-data flags=6 + l2cap-create-server psm= + advertise-start + l2cap-send conn= idx=0 bytes=15 + +L2CAP/COS/CFC/BV-02-C PASS advertise-configure connectable=1 legacy=1 + advertise-set-adv-data flags=6 + l2cap-create-server psm= + advertise-start + l2cap-send conn= idx=0 bytes=15 + +L2CAP/COS/CFC/BV-03-C PASS NOTE: #define BTSHELL_COC_MTU = 512 + advertise-configure connectable=1 legacy=1 + l2cap-create-server psm= + advertise-start +L2CAP/COS/CFC/BV-04-C PASS advertise-configure connectable=1 legacy=1 + l2cap-create-server psm= + advertise-start +L2CAP/COS/CFC/BV-05-C PASS advertise-configure connectable=1 legacy=1 + l2cap-create-server psm= + advertise-start + l2cap-connect conn= psm= + l2cap-connect conn= psm=<2nd psm> +------------------------------------------------------------------------------- + +L2CAP/CLS/CLR/BV-01-C N/A +------------------------------------------------------------------------------- + +L2CAP/CLS/UCD/BV-01-C N/A +L2CAP/CLS/UCD/BV-02-C N/A +L2CAP/CLS/UCD/BV-03-C N/A +------------------------------------------------------------------------------- + +L2CAP/EXF/BV-01-C N/A +L2CAP/EXF/BV-02-C N/A +L2CAP/EXF/BV-03-C N/A +L2CAP/EXF/BV-04-C N/A +L2CAP/EXF/BV-05-C N/A +L2CAP/EXF/BV-06-C N/A +------------------------------------------------------------------------------- + +L2CAP/CMC/BV-01-C N/A +L2CAP/CMC/BV-02-C N/A +L2CAP/CMC/BV-03-C N/A +L2CAP/CMC/BV-04-C N/A +L2CAP/CMC/BV-05-C N/A +L2CAP/CMC/BV-06-C N/A +L2CAP/CMC/BV-07-C N/A +L2CAP/CMC/BV-08-C N/A +L2CAP/CMC/BV-09-C N/A +L2CAP/CMC/BV-10-C N/A +L2CAP/CMC/BV-11-C N/A +L2CAP/CMC/BV-12-C N/A +L2CAP/CMC/BV-13-C N/A +L2CAP/CMC/BV-14-C N/A +L2CAP/CMC/BV-15-C N/A +L2CAP/CMC/BI-01-C N/A +L2CAP/CMC/BI-02-C N/A +L2CAP/CMC/BI-03-C N/A +L2CAP/CMC/BI-04-C N/A +L2CAP/CMC/BI-05-C N/A +L2CAP/CMC/BI-06-C N/A +------------------------------------------------------------------------------- + +L2CAP/FOC/BV-01-C N/A +L2CAP/FOC/BV-02-C N/A +L2CAP/FOC/BV-03-C N/A +------------------------------------------------------------------------------- + +L2CAP/OFS/BV-01-C N/A +L2CAP/OFS/BV-02-C N/A +L2CAP/OFS/BV-03-C N/A +L2CAP/OFS/BV-04-C N/A +L2CAP/OFS/BV-05-C N/A +L2CAP/OFS/BV-06-C N/A +L2CAP/OFS/BV-07-C N/A +L2CAP/OFS/BV-08-C N/A +------------------------------------------------------------------------------- + +L2CAP/ERM/BV-01-C N/A +L2CAP/ERM/BV-02-C N/A +L2CAP/ERM/BV-03-C N/A +L2CAP/ERM/BV-05-C N/A +L2CAP/ERM/BV-06-C N/A +L2CAP/ERM/BV-07-C N/A +L2CAP/ERM/BV-08-C N/A +L2CAP/ERM/BV-09-C N/A +L2CAP/ERM/BV-10-C N/A +L2CAP/ERM/BV-11-C N/A +L2CAP/ERM/BV-12-C N/A +L2CAP/ERM/BV-13-C N/A +L2CAP/ERM/BV-14-C N/A +L2CAP/ERM/BV-15-C N/A +L2CAP/ERM/BV-16-C N/A +L2CAP/ERM/BV-17-C N/A +L2CAP/ERM/BV-18-C N/A +L2CAP/ERM/BV-19-C N/A +L2CAP/ERM/BV-20-C N/A +L2CAP/ERM/BV-21-C N/A +L2CAP/ERM/BV-22-C N/A +L2CAP/ERM/BV-23-C N/A +L2CAP/ERM/BI-01-C N/A +L2CAP/ERM/BI-02-C N/A +L2CAP/ERM/BI-03-C N/A +L2CAP/ERM/BI-04-C N/A +L2CAP/ERM/BI-05-C N/A +------------------------------------------------------------------------------- + +L2CAP/STM/BV-01-C N/A +L2CAP/STM/BV-02-C N/A +L2CAP/STM/BV-03-C N/A +L2CAP/STM/BV-11-C N/A +L2CAP/STM/BV-12-C N/A +L2CAP/STM/BV-13-C N/A +------------------------------------------------------------------------------- + +L2CAP/FIX/BV-01-C N/A +L2CAP/FIX/BV-02-C N/A +------------------------------------------------------------------------------- + +L2CAP/EWC/BV-01-C N/A +L2CAP/EWC/BV-02-C N/A +L2CAP/EWC/BV-03-C N/A +------------------------------------------------------------------------------- + +L2CAP/LSC/BV-01-C N/A +L2CAP/LSC/BV-02-C N/A +L2CAP/LSC/BV-03-C N/A +L2CAP/LSC/BI-04-C N/A +L2CAP/LSC/BI-05-C N/A +L2CAP/LSC/BV-06-C N/A +L2CAP/LSC/BV-07-C N/A +L2CAP/LSC/BV-08-C N/A +L2CAP/LSC/BV-09-C N/A +L2CAP/LSC/BI-10-C N/A +L2CAP/LSC/BI-11-C N/A +L2CAP/LSC/BV-12-C N/A +------------------------------------------------------------------------------- + +L2CAP/CCH/BV-01-C N/A +L2CAP/CCH/BV-02-C N/A +L2CAP/CCH/BV-03-C N/A +L2CAP/CCH/BV-04-C N/A +------------------------------------------------------------------------------- + +L2CAP/ECF/BV-01-C N/A +L2CAP/ECF/BV-02-C N/A +L2CAP/ECF/BV-03-C N/A +L2CAP/ECF/BV-04-C N/A +L2CAP/ECF/BV-05-C N/A +L2CAP/ECF/BV-06-C N/A +L2CAP/ECF/BV-07-C N/A +L2CAP/ECF/BV-08-C N/A +------------------------------------------------------------------------------- + +L2CAP/LE/CPU/BV-01-C PASS advertise-configure connectable=1 legacy=1 + advertise-set-adv-data flags=6 + advertise-start + l2cap-update conn= +L2CAP/LE/CPU/BV-02-C PASS connect peer_addr= + disconnect conn= +L2CAP/LE/CPU/BI-01-C PASS connect peer_addr= + disconnect conn= +L2CAP/LE/CPU/BI-02-C PASS advertise-configure connectable=1 legacy=1 + advertise-set-adv-data flags=6 + advertise-start +------------------------------------------------------------------------------- + +L2CAP/LE/REJ/BI-01-C PASS advertise-configure connectable=1 legacy=1 + advertise-set-adv-data flags=6 + advertise-start +L2CAP/LE/REJ/BI-02-C PASS advertise-configure connectable=1 legacy=1 + advertise-set-adv-data flags=6 + advertise-start + disconnect conn= +------------------------------------------------------------------------------- + +L2CAP/LE/CFC/BV-01-C PASS advertise-configure connectable=1 legacy=1 + advertise-set-adv-data flags=6 + advertise-start +L2CAP/LE/CFC/BV-02-C PASS advertise-configure connectable=1 legacy=1 + advertise-set-adv-data flags=6 + advertise-start + l2cap-connect conn= psm=90 +L2CAP/LE/CFC/BV-03-C PASS advertise-configure connectable=1 legacy=1 + advertise-set-adv-data flags=6 + l2cap-create-server psm= + advertise-start + l2cap-send conn= idx=0 bytes=15 + +L2CAP/LE/CFC/BV-04-C PASS advertise-configure connectable=1 legacy=1 + advertise-set-adv-data flags=6 + advertise-start + l2cap-connect conn= psm= +L2CAP/LE/CFC/BV-05-C PASS advertise-configure connectable=1 legacy=1 + advertise-set-adv-data flags=6 + advertise-start +L2CAP/LE/CFC/BV-06-C PASS advertise-configure connectable=1 legacy=1 + advertise-set-adv-data flags=6 + l2cap-create-server psm= + advertise-start + l2cap-send conn= idx=0 bytes=15 +L2CAP/LE/CFC/BV-07-C PASS advertise-configure connectable=1 legacy=1 + advertise-set-adv-data flags=6 + l2cap-create-server psm= + advertise-start +L2CAP/LE/CFC/BI-01-C PASS advertise-configure connectable=1 legacy=1 + l2cap-create-server psm= + advertise-start +L2CAP/LE/CFC/BV-08-C PASS advertise-configure connectable=1 legacy=1 + advertise-set-adv-data flags=6 + l2cap-create-server psm= + advertise-start + l2cap-disconnect conn= idx=0 +L2CAP/LE/CFC/BV-09-C PASS advertise-configure connectable=1 legacy=1 + advertise-set-adv-data flags=6 + l2cap-create-server psm= + advertise-start +L2CAP/LE/CFC/BV-16-C PASS advertise-configure connectable=1 legacy=1 + advertise-set-adv-data flags=6 + advertise-start + l2cap-connect conn= psm=90 +L2CAP/LE/CFC/BV-17-C N/A +L2CAP/LE/CFC/BV-18-C PASS advertise-configure connectable=1 legacy=1 + advertise-set-adv-data flags=6 + advertise-start + l2cap-connect conn= psm=90 +L2CAP/LE/CFC/BV-19-C PASS NOTE: TSPC_L2CAP_3_16 (multiple channel support) must be checked + advertise-configure connectable=1 legacy=1 + advertise-set-adv-data flags=6 + advertise-start + l2cap-connect conn= psm=90 +L2CAP/LE/CFC/BV-20-C PASS NOTE: TSPC_L2CAP_3_16 (multiple channel support) must be checked + advertise-configure connectable=1 legacy=1 + l2cap-create-server psm= + advertise-start +L2CAP/LE/CFC/BV-21-C PASS advertise-configure connectable=1 legacy=1 + advertise-set-adv-data flags=6 + advertise-start + l2cap-connect conn= psm=90 +------------------------------------------------------------------------------- + +L2CAP/LE/CID/BV-01-C N/A +L2CAP/LE/CID/BV-02-C N/A +------------------------------------------------------------------------------- + diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-sm.txt b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-sm.txt new file mode 100644 index 000000000..ac26db712 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/pts-sm.txt @@ -0,0 +1,310 @@ +PTS test results for SM + +PTS version: 7.5.0 +Tested: 07-Oct-2019 + +syscfg.vals: + BLE_EXT_ADV: 1 + BLE_PUBLIC_DEV_ADDR: "((uint8_t[6]){0x01, 0xff, 0xff, 0xc0, 0xde, 0xc0})" + BLE_SM_LEGACY: 1 + BLE_SM_SC: 1 + BLE_L2CAP_COC_MAX_NUM: 5 + BLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL: 9 + BLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL: 30 + BLE_SVC_GAP_PPCP_SUPERVISION_TMO: 2000 + CONSOLE_HISTORY_SIZE: 10 + +Results: +PASS test passed +FAIL test failed +INC test is inconclusive +N/A test is disabled due to PICS setup +NONE test result is none + +------------------------------------------------------------------------------- +Test Name Result Notes +------------------------------------------------------------------------------- + +SM/MAS/PROT/BV-01-C PASS connect peer_addr= + security-set-data bonding=1 sc=1 our_key_dist=7 their_key_dist=7 + security-pair conn= +------------------------------------------------------------------------------- + +SM/MAS/JW/BV-01-C N/A +SM/MAS/JW/BV-05-C PASS connect peer_addr= + security-pair conn= + disconnect conn= + +SM/MAS/JW/BI-01-C PASS connect peer_addr= + security-pair conn= +SM/MAS/JW/BI-04-C PASS connect peer_addr= + security-set-data bonding=1 sc=1 + security-pair conn= +------------------------------------------------------------------------------- + +SM/MAS/PKE/BV-01-C PASS security-set-data io_capabilities=1 + connect peer_addr= + b sec pair conn= + b passkey conn= action=3 key=123456 + Note: enter '123456' passkey in PTS +SM/MAS/PKE/BV-04-C PASS security-set-data bonding=1 oob_flag=0 + connect peer_addr= + security-pair conn= + disconnect conn= +SM/MAS/PKE/BI-01-C PASS ecurity-set-data io_capabilities=1 oob_flag=0 + connect peer_addr= + security-pair conn= + auth-passkey conn= action=3 key=123456 + Note: enter invalid passkey +SM/MAS/PKE/BI-02-C PASS security-set-data io_capabilities=1 oob_flag=0 + connect peer_addr= + security-pair conn= + auth-passkey conn= action=3 key=123456 + Note: enter '123456' passkey in PTS +------------------------------------------------------------------------------- + +SM/MAS/OOB/BV-01-C N/A +SM/MAS/OOB/BV-03-C N/A +SM/MAS/OOB/BV-05-C PASS security-set-data io_capabilities=1 oob_flag=0 + connect-peer_addr= + security-pair conn= + auth-passkey conn= action=3 key=123456 + Note: enter '123456' passkey in PTS + disconnect conn=1 +SM/MAS/OOB/BV-07-C PASS ecurity-set-data io_capabilities=1 oob_flag=0 + connect-peer_addr= + security-pair conn= + disconnect conn=1 +SM/MAS/OOB/BV-09-C N/A +SM/MAS/OOB/BI-01-C N/A +------------------------------------------------------------------------------- + +SM/MAS/EKS/BV-01-C PASS connect peer_addr= + security-pair conn= + disconnect conn=1 +SM/MAS/EKS/BI-01-C PASS connect peer_addr= + security-pair conn= + disconnect conn=1 +------------------------------------------------------------------------------- + +SM/MAS/SIGN/BV-01-C N/A +SM/MAS/SIGN/BV-03-C N/A +SM/MAS/SIGN/BI-01-C N/A +------------------------------------------------------------------------------- + +SM/MAS/KDU/BV-04-C PASS security-set-data our_key_dist=4 + connect peer_addr= + security-pair conn= + disconnect conn=1 +SM/MAS/KDU/BV-05-C PASS security-set-data our_key_dist=2 + connect peer_addr= + security-pair conn= + disconnect conn=1 +SM/MAS/KDU/BV-06-C PASS security-set-data our_key_dist=1 + connect peer_addr= + security-pair conn= + disconnect conn=1 +SM/MAS/KDU/BV-10-C PASS security-set-data our_key_dist=2 sc=1 + connect peer_addr= + security-pair conn= + disconnect conn=1 +SM/MAS/KDU/BV-11-C PASS security-set-data our_key_dist=2 sc=1 + connect peer_addr= + security-pair conn= + disconnect conn=1 +SM/MAS/KDU/BI-01-C PASS connect peer_addr= + disconnect conn=1 + reset device + + +------------------------------------------------------------------------------- + +SM/MAS/SIP/BV-02-C PASS security-set-data io_capabilities=4 + connect peer_addr= + disconnect conn=1 +------------------------------------------------------------------------------- +SM/MAS/SCJW/BV-01-C PASS security-set-data sc=1 + connect peer_addr= + security-pair conn= + disconnect conn=1 +SM/MAS/SCJW/BV-04-C PASS security-set-data sc=1 io_capabilities=1 our_key_dist=1 + connect peer_addr= + security-pair conn= + disconnect conn=1 +SM/MAS/SCJW/BI-01-C PASS security-set-data sc=1 io_capabilities=4 + connect peer_addr= + security-pair conn= + disconnect conn=1 + + +------------------------------------------------------------------------------- + +SM/MAS/SCPK/BV-01-C PASS security-set-data sc=1 io_capabilities=2 + connect peer_addr= + security-pair conn= + auth_passkey conn=1 action=2 key=123456 + Note: enter '123456' passkey in PTS + disconnect conn=1 +SM/MAS/SCPK/BV-04-C PASS security-set-data io_capabilities=4 oob_flag=0 our_key_dist=1 their_key_dist=1 + connect peer_addr= + security-pair conn= + auth_passkey conn=1 action=2 key=123456 + Note: enter '123456' passkey in PTS + disconnect conn=1 +SM/MAS/SCPK/BI-01-C PASS security-set-data io_capabilities=4 oob_flag=0 sc=1 + connect peer_addr= + security-pair conn= + disconnect conn=1 + + auth_passkey conn=1 action=2 key=123456 + Note: enter '123456' passkey in PTS + disconnect conn=1 +SM/MAS/SCPK/BI-02-C PASS security-set-data io_capabilities=2 oob_flag=0 bonding=1 sc=1 + connect peer_addr= + security-pair conn= + auth_passkey conn=1 action=2 key=123456 + Note: enter '123456' passkey in PTS + disconnect conn=1 +------------------------------------------------------------------------------- + +SM/MAS/SCOB/BV-01-C N/A +SM/MAS/SCOB/BI-04-C N/A +SM/MAS/SCOB/BV-01-C N/A +SM/MAS/SCOB/BI-04-C N/A +------------------------------------------------------------------------------- + +SM/MAS/SCCT/BV-01-C N/A +SM/MAS/SCCT/BV-03-C N/A +SM/MAS/SCCT/BV-05-C N/A +SM/MAS/SCCT/BV-07-C N/A +SM/MAS/SCCT/BV-09-C N/A +------------------------------------------------------------------------------- + +SM/SLA/PROT/BV-02-C PASS advertise-configure connectable=1 legacy=1 + advertise-start + +------------------------------------------------------------------------------- + +SM/MAS/JW/BV-02-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +SM/SLA/JW/BI-02-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +SM/SLA/JW/BI-03-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +------------------------------------------------------------------------------- + +SM/SLA/PKE/BV-02-C PASS security-set-data io_capabilities=4 + advertise-configure connectable=1 legacy=1 + advertise-start + auth-passkey conn= action=2 key= + +SM/SLA/PKE/BV-05-C PASS security-set-data io_capabilities=4 + advertise-configure connectable=1 legacy=1 + advertise-start +SM/SLA/PKE/BI-03-C PASS security-set-data io_capabilities=4 + advertise-configure connectable=1 legacy=1 + advertise-start + auth-passkey conn= action=3 key=123456 + Note: enter invalid passkey +------------------------------------------------------------------------------- + +SM/SLA/OOB/BV-02-C N/A +SM/SLA/OOB/BV-04-C N/A +SM/SLA/OOB/BV-06-C PASS security-set-data io_capabilities=1 + advertise-configure connectable=1 legacy=1 + advertise-start + auth-passkey conn= action=3 key= +SM/SLA/OOB/BV-08-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +SM/SLA/OOB/BV-10-C N/A +SM/SLA/OOB/BI-02-C N/A +------------------------------------------------------------------------------- + +SM/SLA/EKS/BV-02-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +SM/SLA/EKS/BI-02-C PASS advertise-configure connectable=1 legacy=1 + advertise-start +------------------------------------------------------------------------------- + +SM/SLA/KDU/BV-01-C PASS security-set-data io_capabilities=1 + advertise-configure connectable=1 legacy=1 + advertise-start +SM/SLA/KDU/BV-02-C PASS security-set-data io_capabilities=2 + advertise-configure connectable=1 legacy=1 + advertise-start +SM/SLA/KDU/BV-03-C PASS security-set-data io_capabilities=4 + advertise-configure connectable=1 legacy=1 + advertise-start +SM/SLA/KDU/BV-07-C PASS security-set-data our_key_dist=1 bonding=1 + advertise-configure connectable=1 legacy=1 + advertise-start +SM/SLA/KDU/BV-08-C PASS security-set-data our_key_dist=2 sc=1 + advertise-configure connectable=1 legacy=1 + advertise-start +SM/SLA/KDU/BV-09-C PASS security-set-data our_key_dist=4 bonding=0 + advertise-configure connectable=1 legacy=1 + advertise-start +SM/SLA/KDU/BI-01-C PASS advertise-configure connectable=1 legacy=1 + security-set-data sc=1 + advertise-start + + +------------------------------------------------------------------------------- + +SM/SLA/SIP/BV-01-C PASS security-set-data io_capabilities=4 + advertise-configure connectable=1 legacy=1 + advertise-start + security-start conn= +------------------------------------------------------------------------------- + +SM/SLA/SIE/BV-01-C PASS security-set-data io_capabilities=3 bonding=1 our_key_dist=1 their_key_dist=1 + advertise-configure connectable=1 legacy=1 + advertise-start + advertise-start + security-start conn= +------------------------------------------------------------------------------- + +SM/SLA/SCJW/BV-02-C PASS security-set-data io_capabilities=4 oob_flag=0 bonding=0 mitm_flag=0 sc=1 our_key_dist=1 + advertise-configure connectable=1 legacy=1 + advertise-start +SM/SLA/SCJW/BV-03-C PASS security-set-data io_capabilities=1 our_key_dist=1 oob_flag=0 + advertise-configure connectable=1 legacy=1 + advertise-start +SM/SLA/SCJW/BI-02-C PASS security-set-data io_capabilities=1 oob_flag=0 bonding=1 sc=1 + advertise-configure connectable=1 legacy=1 + advertise-start +------------------------------------------------------------------------------- + +SM/SLA/SCPK/BV-02-C PASS security-set-data io_capabilities=1 oob_flag=0 sc=1 + advertise-configure connectable=1 legacy=1 + advertise-start + auth-passkey conn=1 action=4 key=186900 yesno=yy +SM/SLA/SCPK/BV-03-C PASS security-set-data io_capabilities=2 oob_flag=0 our_key_dist=1 their_key_dist=1 sc=1 + advertise-configure connectable=1 legacy=1 + advertise-start + auth-passkey conn=1 action=2 key=123456 + Note: enter '123456' passkey in PTS +SM/SLA/SCPK/BI-03-C PASS security-set-data io_capabilities=2 oob_flag=0 sc=1 + advertise-configure connectable=1 legacy=1 + advertise-start + auth-passkey conn=1 action=2 key=123456 oob= + Note: enter '123456' passkey in PTS +SM/SLA/SCPK/BI-04-C PASS security-set-data io_capabilities=2 oob_flag=0 mitm_flag=1 sc=1 + advertise-configure connectable=1 legacy=1 + advertise-start + + auth-passkey conn=1 action=2 key=123456 + Note: enter '123456' passkey in PTS +------------------------------------------------------------------------------- + +SM/SLA/SCOB/BV-02-C N/A +SM/SLA/SCOB/BI-03-C N/A +SM/SLA/SCOB/BV-02-C N/A +SM/SLA/SCOB/BI-03-C N/A +------------------------------------------------------------------------------- + +SM/SLA/SCCT/BV-02-C N/A +SM/SLA/SCCT/BV-04-C N/A +SM/SLA/SCCT/BV-06-C N/A +SM/SLA/SCCT/BV-08-C N/A +SM/SLA/SCCT/BV-10-C N/A \ No newline at end of file diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/tpg/94654-20170317-085122560.tpg b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/tpg/94654-20170317-085122560.tpg new file mode 100644 index 000000000..3cc985fab --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/tpg/94654-20170317-085122560.tpg @@ -0,0 +1,1026 @@ + +M'&/JP\$+#X83?)"[ M2E=\N*7*U 5)JSKT(5#=>@^/#]IP*[GTZ0%0]$F(/$ +MEK[V7>349??;!JZJNFZ CK=QGD^FOYV^FU>"DK<@0U*##HV\H9&_%["5IK@1 +MA9F,FJO2P^3:4_]04%-0T%9=^XCMWKF"L$[)%)G>_I 0Q?@:H)&1HX)7VY&. +M3 *!JH;^YUJ1[_*7JN2'Z5^*0I&NP+[LAE:>S92BP^T:3+B>IKFJJ8A,4Y^L +MUX+P_C'Z#VN20)A!ANN2@J#!AYY4"KQ\5):1]+[B\TN+BI"AB8NJH ,NZ(() +MG>K?^A\-B,<@/IVC+$#XFXJ<65V*OE'"L]7*OEJ*C]CS^."A/) (K_@0 +ME"&)D)^IP]?+')Q(%NM&7:VL@*6#D!-TU,7.WG SERP(@*R+DH"MPH;@X:Y) +M]X6NG8^EC)N?AH+3[\3SG''R3(?WRGF0NZ#,_4%*E)&>&9R)5[F0OM$A0Y.; +MA8R7%EGBS&\IDPYNR%4ZV$FK^(F[P B/[TU86=H%S^ +MH[H^EYQB:MZ)A:2@IV)4O=//SXNP#%F]5N&<3KZL>(#6'H"D4\DST(O!(![@ +MUYZX#+:1G:V5BE&TGHK]+;@:^JF;;2-&@WD;Z8I9*SB5D+7 &/J8NI6GYGMDGK2(U+_)K!,I$6Q4R% +MAIE9AK#]!JAFCWWD:A8K.9O/I(;D(F2G*6A0YUCMIOQ5M*VD#1: +MG9^)MMZ GIK7,^R0^M"/\%^_B9Y7TLQ/^N?S1 DEF 6XUJU"V_3_U\44H9.; +M6C/PV(36QT(9B9^.C)*YUP?BN>#F%4ST/JM>\*Y;K)J:S+4[O%?G[S[L"^FPVC9/W+).O23U=;?;2EV+G5"5%KG(EED8SLB#Q["2.9YW6IB4DKT QL7P\,%# +MAY^ (+Y+V8GD:B'!S H%G*;=[-\ +M 0+QQ3;G\H21FY_P4-)38+ =K,/38[24B[6W\(N-L/(9[/_LY.X/OLZ%S;A> +MO0TN'._"@/.)DDZ*AGY.V1XW%G7:O+R67U"C@:L%+T\24!11KH^]@[UR\Y\T +M'G.5D/)=H)R"J6R470%+AO24DHF5L -2OV(60>3Z]/#0\HE4<(V%GXBM% 0- +M3X-@G;H%E[2$DL$P-?W&"JI0-EV0AUP(\>] XIW!BI6DO7I9T33VE._FJ(*_ +MKQ6$@E,QFO?! P_#OYFAJ_:"JEF6?]O2PM3:)3"+BYBAK :/H:SLBX.NPOA_3S>U9*&PG[SAU:$=KQR\M>?\!X3 +MZYZ?J;\8N0V1]JOBJ@3;9=L01YQ<:%>>U)-!GAL!T^"]VF8KB/^$EH.ENI:4 +M[(80V,)1T>^'[@;!KIZ5T4.RQW)2M,X;#;8LTO_GV8V[OD6F@JNK JO G$2Q +MH(=0E:GW!3:0E_/T4ZF!M!D-F1F7NI*^QP;A%%V8M*U:R59]QE^+$NONY](% +M28E"K!J#K5N5E8#B_OU9L819J(CL]20ZBF"L4*4D#JV,*& +MYJV<6(JKEZZ4+^NI?%8D<$.P^*4 Z#=7K>XM. +MU3'S/BX/AP [V4*K!EY0C-/CE//ME"./3?_H5OQM$R!7NN&@21#()=Q)MEIG +MU_Y)N7IZ .'V51 ]]L:;LEZ+DI"H^K R=CO:@D2&#^H,PQ!"EDZ>@'"*JK)I +MM9<-XF7"=^(HC+:D156UME\ U?+P=G >A(^3=EW1ZB[7^C_1CZ&R#Y!"F:FH +MHO_0SL+1D%1$55K!?)*MLC?(]!3G_A,(AXY&\M.G+@>5;>6Z]?^Z&KBV:9N< +MBRWP0KI!\#7P]MOC;Y)<5(NN%8*2GEL9'\7/SMD 1Q6PCZ]6;0T*&KK)-^4N +M-OV!3U6TE8(,B;9"K*0WH=?J*<_9J=-(NK)0LY:FO5R)P'*3V.;%;^Z6() 2 +MWEB>F*H-#0RERD0TG[]6I4)#T_26M/[GQ8V5MO]RIY&RN%W_S1G/L829DMR2 +M]('/K/92XJKUML7OR!,>P)J*"H>&-Q0-\]("+'L^-EO>=(036Y>P%.:V&"8V-7ZT139&:(YNN@Z VJQCV=M VOMJ:E/XOE(L[GZ4;QT"H +M$!AY7Y>2^:N K"-$'B0L[FEJN#[Q19:D[2;=9F*>)!$@X/4']#" +M!1&2G)8;"$M&=?M B=+DQ^YQ"-!FB)9'T\^32NDK[68N]-J[6Y^IR:Z(A[.. +M6RG95?0:6^K'2FAK[7\O>>+_9#G(I4O*2=3,_<+@R)UM-9DW*NL+I?DJA^ +M:X8+&-[1=O9MX:R#BIVVVL*?&,-#U928LBR6DI:OR/OQV_;Z"H13GEZ <)J[ +M^8(-)]\+U9V24@V?@HK_A'3=YS&MN]3U&:<&)%JJPHZ6H4 --!,T\L,(ICBY +M$XOXI)]-\^"U_CHZ!52.^"'OK$V=K;>;@,34R_HCW U3FB1#KKV/@Z#_S.'% +M9M 26;U3E76LAFN3DZG5@QO8R.G+!?N(V9N<2;,*E9E2@K&$0L$X+707X.^\ +MT*.^GE""6H$?\19Z=D.11X"6D]CR\RWCD_%?L8JF/FV$&X]!:4**[ +MIJ&85T .P5K[]>8?Q92+TN#S6X[[MHCH"/&KV'J%?' +MDXN2D@L"PEG3X\S?#I9!&(61@+:/6K0YEXK-.ODV/_?'<;&3^)J!2E##A^,3 +M^E;>K7N=]K<"P^$PWC05A%.T7+ 72YJ2?GKS[_#*?9/+D5I=DGF1MKNMU-:; +MTA'SN[>Q@KJ'7 >7QXCJY?#F JZBH%J*TH7WD[S#-.W&]"["KX^N/$.2E8- +M\'OI3>S9)=OP3U7$O"FNK.\J5(+0IC!.XWY;M$\. +M=$Z/KD^-C/1_0?_L_+W"8^N=B7="A8V64I)?G0DOR_KWS/WPQFUSE4C6DDBH +MPJ(PFL.YN.[W]D+^>+I&EEF\EPW'VQA<& I.AD"V5P+ .6_&1:%>-O&=E8%* +M4Z0_F\3GXHI]D-*1FG<:^(&&FQ$__=_Z\-!-I[N#]"^O-VP$ U1GN0\!K]*A/C9:4F99SFM+[ +M[/?CV\*/O(Z#ME:'OC&&?BVA3B31],CN[TF*EE6"FYY(_IXY];+QIY%OQ/?P +MO'*3\1.ABJKLSL+ 7[&CG)>!3%[%>BSWMCX#>%VV+I"SC'*XM%O%*Q$\F$3R +MFPZ16JEA@IM"\L/P^B,0TK:X6KG'%9"W[*C0N>76+Q%7H<_>PHYZHI3A)I%T +M'CJE1J;\5+\;VP%IFYWG(<')6(D;XR:/K)56#*O 5YC#VK;WD_H'2JC>IQI2 +M#Q)4X? :TPVM[5T "L<4HRZ>IZZGK_N#H)Z#!2#PQ>W&P5H#TE6?DII]0?_U +M&*Q64E:.A]I>Y.KMN_K%\W60 9M4G7>#89>?AQ=WP<6$M/BPF(@#DXY8H>HV +M_98"]E%UHB\\ASAPD.K1\^:UE\.K'Z!]6YL*DABNQ='FFM8U\J>$N;^)5E:; +M)HY7P\"EFN02YN[;E$Z.O[U&K 1"I3*7,,8PB6.?)NNE%"<+^?)R\BZB9Z6IC<;N)4W +MEY_GY\JLE%.13J-^"6Q2BLC7\M ,DGJQ)(E!VJ2>JL$T&>X]XL(MD$C9 KM8 +M%Y>>1_Z3H)?PNK"UEQY;MXY:G%GHQVX4[8_K5(P&CO(G'D&LVCKQRXG#YNWUT]23B'FSNANK +M@Z20C[BBQL4UU=+ND/(1D56Y OC->0^5A'RAD:0)&OZ$T.+\%E=K2E)F21L'SG5?CVIO&C8Z+K@7F\3[O\+J% +MK ,6OHYV"U3WZ=%^O_I*[+2LOFNZ'JB&3Z[%X$%9K\/(9II5A+\>CLV44)DG +MY"7V/;KFB)A=4].7@ZASJ'":Q?OL=UEIJBM)BH:'DOQRDJGTL!*[0>HY??Y= +MFH1(OYRWAUJ2T4S+"ZR@FZZRN4&HP\;T]IH2Q9F!DZV225N_C9);$_T!Y9J6 +MB?F&05X*DJ"#A3HS)L?'&@E>::Z$F&OD%;D[>K$/HNT2&C7!VF$ _$SYEG(;VM@7+&[?+^VI-.F;>X +M4$N*I)"B-MC^$ ;YV2@#T;JXA(JZ$ N3WQ-JL"%2M&J##F86WT/BL'P +MY.VZ(+&==J "\H:'QX.LP/#E[>8/BUZF'QI-5Y"0G*"V[S?D9O%'18Y.OQY. +MBN.WELSHV]K#\>(NUEP8;K>_4;:W^HE8]=?]M-" G)V?4[6AJYZ2EEO(SYH. +MTTO,P0*3G@V)GMG/YD6U,L<2Y XGUX) +M5_*33$# Y3?& [B;I:JP:89:E>KG^_6:7=8*G*!8[&^$;(Z@1KQ02XQR>D^[0?W8I/O-HL#UDI)0DZAU +MB0)0^(Z7S,)\T"?Z U#6N@25I]B*U0;.UH2"=%]>6:ZX\2'U/M(5U716I!UU +MAU>VX _/V?RJT)V2DA"&F9I3<(VJ\_9U\.#3L9.F9)JHII.?H+_E_M'N.AC' +MLJ26B+DMEGL&T.?A\O3"2VZZG P?TXM@[/:MS>W.P<\+W$D$U;_/>$NY>I>X +M@7(U+^;^3T^$B;-_E[M7GA&.60E*V?<3XZ;8V;L]]0J6EIF<%& -J5L2]SOF +M)..<4(JK6EB.FR?/*Y/*3^&/#W\G-)F'B? +M_I^'2E1MGHKG[)A4BPP,6SO'#EU2L@8-FX'XNKJJMD?P]A#56)N3GJ:]0(]# +MKQOCD)&4K4(9#][#/G_6O= #>+!255^7FJLR<%C8RX_1K[:$A7N@B;OC]X-8 +MD<#T'M<6O7NCD]Z'?G!;B/,JPSIMY8V7L!]:YYA>@(CT]#ETYC7;3**MC$LL +MGITZ!Y[MV@],Q_+DGQ6>J,^3K(EMA+=-(OW7L//1@8:QI5G:JH(>;!2"QRXJ +M+R[F!=L=DUCVD5J60+I_Q%R+1_*UQG;UV46@EY],D=";@:GC\)J8F)M;W8R; +M*.+3[O8_Q?!5A-&;R((_DEJ? LG"R$Q\%E20$:^YD96)27[S\]/WG8,";9:< +MB\;UOXW--C77[].KC!/_VJ;VMZ.4P+KM^M R]8]67@PGA[R'HA)=V0W=!13! +MY%:R5&I>GJT_;)R Q5/7[);$"[J:>U7SEY&\5B95RW<.4*_2T\;"V(-3OI]Y +M\@__\X:4/1J3QT3^-=.JL]O[I3=Q1GB=J]ISE]AB"MH2U.UFE?U7^,8K))8C=:WBEBA$ISUM_JO# !"7X>:K!ML#X,"_.J= +MG!R4+TY!FAEF5YO2PO$U[*- [4:L7U8]CA>_O)CFP<7;TQ"2IKGZN5>GGPAS +M.;5>5A ;3I:$O*=[#2@N0NZU'H$O7!BZB==5R7@K:4D->IP,'V\CHW@)Z40(>&U;>7 +M1P/+%KBF6Y]?D)!6\L'U->V;]1S=])[\45:#HI67Q LF:<'M@% 1!+V?BN4)3P"-F-18@GM^ +MB*CJ)3+6X,]04)Y;!?R;@V&PFM7.UT&$4!&III5*O9)WV=L2=^YN&LJ[%^V> +M^8,L'!J(D2(FN_1!#SIX%YN/5E^Q;BS"YO_$/\M-5H2=KYR&T+"@GN#,(?G! +M#\A+NYR\%)V%/7N.>R3Q[._&\]JK7Y"+2Y>*JA>IIZE)7I@*XWH6T32[6]6: +MDE";E_',D)?HU"T:YM[A4""1K*)S\ED S^+T6 O:>(>5&_W',OEWT#[C78"> +M&9/2N;T(C;VI#ML)O9.24?.8_!ULCY#%%\3&^]DT8IN UZJHKOWRJB$S^58O +MVTM:L8-\#__SHTK3:?&_L/#V[).5W*:>.9*3O%L"P*T-[H-"IR>MSFR?C*V, +M7@BBPF?DU' *@?*UWU>:HT);D=H.\9>.2TT$P_?4:TX,\+NFJZ@";%6XXS;N +M\O"]VI6&I%N&,+:S)2L3YC&CGJ]R")Y[PR@P[;/_R7I0,$)*=0Y7SNZ"6D_%]Q="M%!&:FJS7 +MEMDR]?W +_V8I>";BHB]UK.,S/(QE??CBZ9@20F__):6I('^/,;W]=B/6Y^, +M@IA>B[!3FPDMXWV\C 9CG6)O96G H-MEHO!3L#FE)82CY>(F8FACI^'F^\P\%K0YJ>( +ML\Z3DHZWO$DPP>+ TPT@28J,F+R&64#!QNR0/]!8CU::O8^>O6>AH$+!S/[- +MY]/4CY#_N8\NCTN@6[?1:OF6]?7%!U>?7UKPC5)"XY*;\,82 ^\%R\-)ZJR9 +M7UK0FZJFL%>MTR9W-<75I9A0@EOP6)^=4-4#Y@^CDZTT45I;R?XY9__P Y!2 +M7D2 ,)(7HJ8:T<,*_863^XETD)J;8I92Y_(E]B_3U(>2X)WV2]:"AIS''MS^ +M-/*(EZQ:@^W7PK6*(.)9Y/8PXI:"! Z?BZMI1I;91/[)R.7"MNN:D Q'^KU<\5$<:<8!WC4$,SLT-V_Z M$U=GJ"^3D?;FF.T@2?V +M/K0[HE"0G'@_UI2;]]COX1F<%%&5CISZ>\3'Y-_Z-/.JEI.MH-,7JJ9VE_%= +M,@YVK@V2V6]?*7-+JUMJ/6I"5IY^5"W.R$^'S^486[]%* +MKI$C6Z9.F*)@GKB'B %&2#&U3&8K:U9&J81DY*05ADDPG'6X$8+D/:8<+Z) +MN-DM1\'<6@O>?07UF%C),M,P]/X*^GR3AU99G .AEBG-[=NPF9+?A(Q=2]N$ +M3Y\"DKTZQN49B(YX&HF'3K:*FG,;O3KG\ZU6A/.I@RV&4(KP^C<\^\>E#*1% +MZ!F/CKJYCIO#QX&,RV;0CZ)=J :>#8N")MLI<]7V+._BGI)]FQ>WD5H(:))7 +M8*(+U0L(Y^-8N0X9$+RF0*I?K,Y7S=0YU/Y$\3CVHKREH,*!P0,*T;BFHXV. +M7;B-1='8T/OGR+F6O@Z65ZFWJ'^;052%R)&@$5_ 9[CIPQ1=7FHV9>NE*HH6="LC/ +M2-'6V$:D7!^]AX]O>HW]\3@9I^;U\Z:8G)M7LHJ*T'"@4L$-^E[3AL[ \8K= +MN;>LF@^KLZF0>MCPEI/0N\=:=C>(EEU*5N4,HN"4G(H=I8D2C +MMJ"?DX&;MP6R*N#-PW:/]WPO6PQ)%,%VJ:ZJ. +MJ*"2@0+#]^_N]@^JAX:?0J:-O'&1SE>@COOE".;#]^9)FKGW"?9##K:3L'JL +M].TPY]##+%);A/H'0EL'W(\0CY&TMU"G^KG"XG3:M";)+'G_E:!=@JNX7)F) +M3T4QOG0#F*7WDZED%C="PC/[_?%4KH^64UAKV%*U0=G'[/04B:N2N,F+GIA& +MB97"X^[TU_971:1]B:=6N)U&NMCPSXOY#\[9O:.=@$,.0:B25[L'/O;%TE+/ +M2:H9@YY7C2QT08^0S2VJQ\<*U4?B/]2=I5NEKPN2\+:+(O+'-^X^YWF@DYN/ +MHKR7)KXL-1;176O#6D!?FKJN&QW^?C\J;DNQV +MBZ'6$*'/'ACJTYYK!F]%LOM)X9&@F;F0,'![/]D:.- +M6@C^ N/$\2PMFL.8!!'UEA&8GN2FGL'#0<05D)X=FJ*[F(&6]PWST-7$\+2K +MCJ2=>EE?E=*\Z?IMU#)+2IK* IQMAX!:O\JJ=<3\]M"+1I'JJYZ]"*2:G5C< +MR*5C0/&/5I")E(RNJ_B5VLT^.6(ZED^'NX]3G_(MC'NZMIG,S_C5_2?9HM&> +MG'BS>O!FBY.LEYW6(OR_.$QA8H!T494B8K,]'35DI1& +MN@@1A)^2_@VAI9E2XLL05! 4W9(U69*P7E+1\/3[E]+@FX6AL]>-#8*!O**Z +M/:S$SS^ZQ!JKC87[B[@)X_R@QOP%N?>IO(*&A<\1LYLA#$S[(<=1CO8-K8,: +M;(J0]XCG'_F@8L2:HKQ]V7J<9T*4:%9;04[J"^.+T<, @5^[HIX7N[N4N_!V +MQ-[O$/_D<)R"D+VDR9Z7 -: AA"$B"R5G9A+!_#@_%;F3PJ<4XZ0E5>KL!(J +M],+:DH_"0]^D=((*H)I?V.@U;<9ET8%0HI>H@Y1T YCU_F?P\@-)L)!6UDM. +M#XLMI\ 3]]HP U[WA)Q/.$'/*%"!]]3!:I[U!@<2^@J$F V0ED19VOXSUN;V +MXKBMJWZLEAN:6*P6F<+"R ,/Q^'W2(C2"4N:$+N"@[B0F_+;Y28:,L"\H)I? +M]ET;B_7,YQVOL91TGE%:FU+K^>YOUE.?D_ %LY/^FTQ3FLW_J39\\EX4S**Z +MF:(&]MGKP/?5Q=C*G*B76&C=IEL:HL(NFB?AJ51RJQKO5C!)O '7T_?@[\*B +MCKR<0UQOBV"F \OL?)D/Y1:#Q/W.@]X.O9)7B4B0+MYR=1DYL)P\??[<[2 +MRU*47U>'#*6@O&5B$?I\V+^3H%=:4K9:GX0!5CCZ\_X/:S9<@:^&5I-PM_O9 +MBERO2_; 1PY?A(,/AJMKG?DG,?]^U"?3XY)5$*S/BOF!IC.XR,C0(J+DR\"< +MQ[(UDU>'AZGX(%:7YSYCYN;>SQ"0B]TV 8NHP0[ \_&6(ATF79>O 3#SKL9O +MSYJ;M/$>]UG^L%Y;&?KS')ZQMJ^FM)):AD87"JOC+/H+,D>4$9J?DUW&4HHG +MX#3:-\F-J0>LSC +ME\";IG1["//YML:23[M=KU5ZSN\6"&6VLR$,Z O'!\S9$"*V>YL C:J=K^=5G>?]\E6\S!0\Y2?DEV" PDYEM?E]CS]_#7391&JIG+ +M4E^5'<<4+3+N;O*.@ER>%(V^@I./NHG$Q,S5P/!'M]P=B_^!;SA63Q+K^3OE +MO\\^EIT?2I:/&DFF#[C!#,"G^\_^Q39JNERS6Y:;@Y^QAE>9__B;_=IK49CS +MK821OX*1 O;1F)&1O7*0F%# T^3"=L"C'8@)M8:S4M/&>YK:R0_!CIB;E7*@ +MJ;:ZD'L(U#EZ1L,1F2:@2UJ-6$WPC$CJ_3KURHN_AJNL1Y)&$HSRPM2ZUBS' +M#I2(3L=:;XUFXC +M.HNR(@->1T^:D(JBY_62- -#6C@!EIM/E:6*23IM?]>20:D&#>F,AI2[#$9^ +MZ,_@^,4#X ]V48P6EX\8H 9:Q_1#-/+N#P*-A8**1D">5BF&@0D"B<\##JW9 +M-=BN!+M65;CYDJ&.ET<^*$X.>LK.*'ZBB+2#*T(95U%2=#(&:@+*@>_,T.?;0(+!+%$&;K&J/CY#* +MHM+QTI(/1_ [O9Q(A)):NL#$^1)GYL6,GK&,5H>/:Q!>6SV/2725PU=[ U>MOEX]2N/^BCG(,M%:DSM'B^X);Q]:]F"RRDI>KL()C +MIE<#,KVWF^XB_[*7KH+QKE?E:X-ACY:1]+ZW6+/9(L7G[+_S"K*FG,>\G'*6 +M<#G'W<>05).VA)^%KE."EACQ/N;UQ"?;O5^P"5@;OY!35='"=O746TJ5E+%3 +MA_;F(" 6>WO#^1'T'((FMD6&\.WL_3B..1& +MQU:MGF&KFDM\3[*GR3+G\!K!8)9F*9F3?9J;O_&S[.6UQ -?5X> C-N>HJV. +M6/' I0"3T>96:O[58O*>HJEN5I)[!OD:2=N G'!!>=(*9KXW5Z0,0CM!SE4^9OI,*]\,Z +M=&?/AG&4G?69 %>QM_O7'JO;K?R^O:;97JFL'?L-T.$_^B+P2:>&.1/95X>B +MH%GT./;BZ9?;OV-D<)]E#M3YRU$YBY61 +M[$^.F)BAI(MQU/4WY_32HH^[VJ/; +MJ:-R_Z4 1;EVI#V&6.S_92M2&V;I'9*R-S!T,;VTYU>K,1)EI];N$>3))'5 +M$!3[\+TLFW*6I:B<0:.20N?B3@\K!F6OT^L/J8B#MX]+>,2/./%T.ZN +M6*1Q'I&^FL?<]M"?H)1WMH&:OUG^_)?F]<"=@#9>II%+^JRFOL46PY;^O<&- +M3I>;O6I:&_<3[=+FPQ"#A$KXEDN;E_&*&SIU^C7/$[:&>YPG)GH.EQEO,Y,$?POKPG-9QO(Z)UXNHPMKC +MK***N194FK<"Z#/ZW^;;K8N7K/>7XKM^^?F +MWB$269JXK1.14E;Q <#^9I+2:U*,AE^;FY)7@L?:PM,>^FS2O_"8A)^^/KF0 +M4AE#1<_(]=5T3(Y_KY2O60O(M%^9M-D2)U*!-/;RT)+C-?(;L9%2L-*;AS^4 +M=8?:P_E[YA6;=+3_$BC=C8#J31.19G#028S_OXY"N%RHI)0+0MZ7XMAS=_\^L;%;Q)( +M>IRG5Y>5O@3CDS[F/I""D%6*CMR52JSUEMD<1OT5V1Q&O[F4:7Z6BZ#RDM/B +M\3;RU\"2GBB3K%YOMYJLGI_-5@OO^0C$4D-7!@T8CUEI.#DT_>BKQ,\.S2 +MNCO6B;JMA>]R:X*J6DT(S\O3]L\1S[11J!:+X8-@1/W3\O/0+OK7 QZ>H9*$ +MSJFGH*>=#5?HP$:CY_]@JA,C992@Y>MV_#PY_ EVU06<+E?E8)3!WVE +M *W3H-"F2KI;9]'YOU +MQOH*UJM.1D.)C01P2.B-_M?FY<,^AFA0JZL&MJ<4<<34T#?6(QE2VFCOAFZ +ML(W]+?H,[UR@Y)>$C8J_FXNGP9I(TQ;WT[ L#Y&8G-JJI(B>T^!6^-'"49\K +MS(KE18J5D2$#CH,(LF!=PU'>U,+:]<-4$YN\D@$"EPS*T[65B8N4AAFJ&1?K +M[)?RP@MY]I:MCZ% DJ&,DJ?)SM*%G(.;F@*^5L)?U^5[T2?&SU1*G^V;@X>] +MU9;%P7)C>CHE2)9!NP&'6YO3*O$S_6XU^O+"A'Y 0JI;:4765Q',R0\' U6' +MEH6437W%1J"6K0=I[7OW]L-*CH2*WE(+F?&H5E*:[M *^(?1Q0B+5)Z@G!:[ +MNH)@7%^A4!6^)B+G** +E-")N9K+!M+DK_K+W7!0@H_G]C3P\K(%_Y&>L?+% +M4[T-NH+EZ440G)12*QH9FIJ5CK<5\O?W\\#)CY:A^U.-J%"EC,#Z-MSR6(>6 +MI:U6RUJ2 X_ UM$F-/?SAQZ,+>^S6@R#J&$;)APO!9DNOKW"?CJNJ6[JEW>CY^77P, "X49I;IZ"3BL#% +M)O11HDN$Q*5:K\+2K?#&QMM<5(.8LB&V2X9PJ2G_ZU&?H(&>GY._@J)/F8+ +M[3HW\N"ZC\&8\8]=OX.^(>'%GJ:A0!DC\^8WU\-71CC825X! +M*J8 D,3J>,7NSMQ)C\Z,'+X50)0WBN^+G*(DJ5VW@H/!V2.)CG 8"L0#T^P,:N+ +MAZ17B<"KM=8N*(G7H/NN37^"7Z#8\<,Z,'K*@XY=X(M22T>26K:CP-7?WI,8 +MBS>L'&FH;4\FLM-,WC?$/!?S!UAVDK86KU>#D*:QR,=J]+,)4PI(6"ZZ1\YFZ2(NHJ' +MF).=8Y>:R.+:P8^;D;ZPD5)W!8RXT/;Q)O;U0ZE>.%S]]!NI^Z&]DRQ +M=IJZBH&B#(W)@@7+QJY;ZT.[MZE;"*)=7Z+CUDNM(N?^P-3BA" 6NQITMBT* +MBO"+_B*0'8R'G'O@]O3N>OKS3$G2^0^(NE<#GGK#S\M02D/Q_W:4RGNBMXG! +M,C#V[%#EPY1F0UKKGJ;?3B7W]?0UD6-WIJN;AQ[%F*7A]#Z:\._5BY><3*O[ +MG3NMEDL- <;HR\?PEH!<5,3RGK^UH(M13\M"4&KJ8@I[[\6/!\^0GF%O[MH.2 +MB+WPLL#W]_4P-!L:D$Q=NX=6!KM!T=XY.G#OVIF:K(V#!ZD9N%K#PQWDR-[% +MY ^F#$SLM[MJN%ZHP4/TYA8P6LB_EK*"?E*:"^@PEV36 G4*_[GW-8 +MCY."H[G4^$BKB, +M5P#4V=/E[E.#>'M56@"Y5X*J@7(/PTF<6 +M[N6FC NQN/>0^9[$PJ75WJ6>65J=BA$A:[E3T/W%6EB G9>5JECAC%?!_0]) +M\* ZA9:AFD*!GYO8\O;V<]K0FI:4B*NY5I1'C%#V=3:V Y*[DML*N)>4DVH( +M].W&-,;PCU8)[9J%Z[BAUBW*S.L%3R+8EW:=C$M5A)"I^I[ NN$0XOK'S;^+ +MH:HFYJNQPEK#$L9)Q*OL!P\VAK);4*Z@K_;1H8X?<,/3.C_@(X1V?H>ZD+J3 +ME2IA^,:IRG\JP'GK;:Y!"#7FQ LY/=EEZ64O(]W^62SX^V>&W/ +M6XV I%^IX,:)R4]#FF,?J8Q##:4T1.FJW"+);'V]R*D$:K +MNJ:6\)<(D_GWQ'XBIIKBB1:=.O(0JJC$)-_V9D^GED3EC(9?3<"0O]G_J,D5 +M6]8I1@^-AYB.B[F0?77^"$HT<:+_=&' +M?@Y+G['&GXD*F<'W]<8*O)""B1X'DIO"_]J9S-02F[>BFA#C\O,_[N;)7[R2 +M'02(GHJFE[K(P_#=J$B;JZ8E>_M,%_T16_#"?O(FL1(FT<%+)S=;+(=B63WN.CXF:F;F0 +M5HL2N^3F)?S(DP>$IK>WDI8@99^;Q>QYT\'_C<\":7^9PRF6NX)0A* )\<#W +M1G'. +M03CN]L8W\X=>7#VO5:UOS .:S-P.S>O'X@J&1-1&CI2;,/#ZS/8M[AW^!Z], +M%5,;\JZV7B , QD(J,>*K#?><\)*;DI 4NO?B>>#WV]5-ED914*'Z +M"\SNP_91D]&-IEU:D\/6N-65_L\=O88?4]2:7;"0EW$'04F9D,I$IYTJ6_AV +M@PW &4?ORV2-6BR:DJJ*IM*IX=0LWI)/ Y*DDHI8BEN53?$Q_Q8N5\6LFE&Z +MAUH%4T9-S2' ZP#2AM"?SYV?BPMEGN%T3S%JO%I>IMHO: +MPX'$V'S)\]P;FK2%EZ9-ED.@6EOB]C]^W_Y!=8F*CO67OG/A(],5K]A*5))3 +M7X.)*B#N0!*+,!S;G*1QEY*CW#U)_X+<&-"6/(ZE_X%[EIW2T?ST=\/+A_PU +MU_N(OH^E;,&X93+0(PN4H9U!FWQVD4QEXY;5YO*!E[I0"9S^H2C!I9+2S(TI +MZ_'+KH2LOX:/O*J4$%/Q,><:WC7' SA0BKHW[KN"#):=T5[!XNH-S:[8D5Z% +M0YN60IBBK8^;I?;DQ=3OHZV6&'B:HJN=$_ZC&;&:4?R7^).1PI(L_>;$*5BQ +MF_"%\5J7::6^@7SQPIQ1HIZ.B/);\HZ9#/#@^A^GUKB'PI] CXN?ATX(PM5& +M-_.Y3A 76X?XU9>7T,'E+9HD"I]4#X'IEXWMQ89]PLP!Q5U%V[NPF!6-/D[- +MJ >8S9(Y,#J[Y6&(3-> GDN;FJP/N>+B"-[1W*7;=(AKLJOI9WJ/7_ +M[3?N%\^>E*>KFDB#D2W4RN"5D'Z,FM"9T,%^P<7$/E,?EEY>FA&(NN&V6Q3# +MP-NX64[FD0H/D^=?PS]!"AFJ/J-M2EE.X4.)LM!7#6Z:ZCZF0K%;7 +M:M+"+5/U]]57''F5BQ>=2[I^KRB**P_CQ]SNM%H-F1:EH(@WJT+P)NX6[/61 +M?:T1 "*"BX)IA*O P_H!Z^A= ]1(F@L@VD:K@@2!AIK'PD7[U]/CM=PCE=*7 +M I<9QO,54R@DBCB1Y'E^4]D'? WJ>9=IJF +MM9TKE^/N-_*;HI.@4H&/N)9)E$/S^,9V!]E08%&SBKW.G^_%T,5_\L/V@U1Z +M:FU&:VF@I+_3^-:OWO/9GU>6KHJ=CQJV_XE2\?F:U\8GXYK.OZARJH)0K Z> +MZ1@M]/Q_S.,3RYZ?MT*ZJ)J2IG")\Y \]O8T 4>\0I66D*B!P4TCT9GX4I". +M49H)V.+T_Y VP)2QDX^6<9Y0DHR=V>?/^:PCE%L0\:GY1!^# L#35A?BLDJ, +M-E/9NI)4'[R-ZM,7N]6? NC_6ZM.)J"_\.@1-_!NYHU/F=6;6%6[(Y>3R_[) +M+0L32@R&6KA#7 5*I%I!*/B3N]KMTXN.6P";CD&:0&RRN^S\V,;("A^CX:N- +MGH&*6H;^D('^7UDQ^4;%Q-NZ2%^6AE*?^L+_#[8&B9:[$'<*N +M_I &V5;(&=.9LI>3KZ4?\304]B>*ICWNOL:N@Y*GK5B,#H3! +0Y39Q.29H; +MBZ&7U^[U'"W>!M#+J#V74Z(;&%.@5OT! +M]"5N1B;BG*!QL3)S@8G#6L,:1Z&+C573EINHXFSWP-> K)*7D:9=2XM@!JC3 +M%P+ESI3T!O9\BIBF6@/-_NUN\"71BPY$]IZ-TA11J!":_)8UVU*^)I>2DP^/ +MH(^-*;SL[; #2869B$6'G;ESFHKPU FM!L/EA7>_P#F:P8^X%?DAXFSZQ>_U +MJ0Z(EKBZ@4NAH%>3".SIALF):P-"H[ROMUIR ZX?DG>"C>K6Q_ILP-_\N@Z% +MI8*ZS=G1UEP1LG:U\*F*S?G&YM(OVKI=MJM[MXG[>)>"T<\@M'Q6DY^46?#Q +M((*HP78W=C?/X$K=Z8/\CH7<%:C%(#/']L6Y>^Y\4&>KT]M26)\S6 +MCXP_+>^M+*:? ^K/$,%8\,*T18^+?HNK@IVZV6@5)\?@((QQ"0($FO +M5H-9D\W^->;U^]5<=O.=1HJ*F*@, _#,UU&_MI&;<'%7F+A>J]4R?; _HMP/ +MI&)"D[J&P%75PN+_[]+6D[7SDU:M59*:O\?$/T;Z)B:.FE2,EXALDRQ4N]C +MUH55#V OCE@4AIP/2*/;_V$0U/Y YL5*F];95Y"]G+.REILBABFBZ?G-PYV( +MK+V F):;7K>@7@O!8D:R[M)GO)*TG(^8BJU!!-O@4/9R_I90UD,G,_,_]^Y& +MD<@+E7+0@=V$A:_K+2\;D=Q4F170BA>[L%GPZGG;[@*6OP>,2*A*A+7>B 'Q +M^,?0 \]6H"J1BIH<0X[T^C:U[/7#1:1VR>/_G;O$G?_(B$]:Z\76B9Q*G$>& +MNY"[IH-U<'FTPD3.ZT>LH-&PQ[I3K(VWP>KZ"L>M_//3D7+57YY>F)HVIE6K +M0O#4]C3EX71TI%$&H[(MD-;;V+FXWE^PT5(ID/INVC)6H*V(?[M6FIF2N!XK +MQ8DI:-B:RI,\;%E_*''8!=5NN2 +M&O\!Q\ W/L>OSHO]D.V-3KZG,/ S"0[>H\OE$%Z?AYR'K$R#,[!XD>G5-#IF +MSQ":A0B,=>J6,[JCF0-*_/4H M_RP9%'C<.,I$:P0OA0BP*D]?XZ.Z:7\!*? +M4@F;JT+OPOR0D+"YMY&L>M?_[,>L=J*P")Z?=H&IDZ8U^^/%X4C\5J*HMG>H +M6*V,347V7)?_YU"=5G*9M@E_EY"\X4'Y.F[78H>0^HAM&J>#+S7!^",7D"\#!VQI)S@^EEUH4FX6'MP$4$SH>E\*[EI674G*XDY8L +M%YT(Q='2QBGJ#U&Z])]>L\:JG+ZLAIOS-CD^-# #F$&P'J" JYN'+0&P.G(* +MFUI94ZCQU/GPX"^#]YA?G/J")PM?G/:]^?9IHY*5^FNE5.&C[K! +MP'U2RR+8XQ:4Z)RR%-BDD%$H\O;%Y?8 JS*=TKF5Y[H>H$8 \0X$2OC+ .76 +MDJZONUKZ2]Q:;81XB>+%0/OR<:Z4AE$2U]J]\*W1BH9)B?T:6)>"Y_OU]?H^ +MUY>A@IU?DI)8ECV[S>L'29&PD)U:HP.;:/:= 7YS?C3OUKM/L%U2'0Y6(0K8 +MP!'D]^>;H&R:ELM?A(- 09^L\C 0VT,0C(KM7^2Y089+]/KNR.=:V$V41DJK +M3;ZYJI29\RO1]K*T0J^>'4#7GXV2DX"&F6<'[,7JK[);=EUV=V&D +MD^C' +)<"%^9#KU#N)*$2-$^9/8^)I!"C$!^F@ZY&-1?00JBWZ-7?GP.V0I%:0AJWP\HG ]#;Z]!): +MGK2'[:_8;-]L]X+8W.'JI\$)AI_>X%Z>K:JYL(,*]^W$V_7PS9*57ZI64)R^ +M,_6N]0+ITOZ'XL$QG8@>M7GTBU9&B*6S8*K&QM#GY7J+H)6F4I/SS,M2X?V( +M.H6UTT#S"1[4QCI]PP0R6_R>5UZXY9Q*]R+2U86BNE6,D8G#>*3]X\+Q_^X% +M$D+R(%/QQKA3GTP PC7V']*)5[.^FH*L3Z&< >+VT/;%B,>-G)Q/CHF-D(V_ +MP/S$S5S VZ_:F$B'TA[J[!?_$_?]PNXTSXJ,51]^!A-RE'(0<.W-Q!;.R\/" +MU$;:!:&7HHU>D\&:NP#S[S8R/>:X@Y^\E%BZGLD-HQ)0E).TP%R6"N?P-9WV +M\@%=D9J-=I*KEY;<7TC/ZH6%G!.,L)":FS > O?R)?;GVLIH]:.#FBV*\+%- +MK3+%DL8!0(>@&];FTX)2E@V6Q-;VE@.6FK:$H'(54W'&MB7D%0: +MZ9R!.L"F"QD2T]?0]"6O"(4UJ@^/0Z1%E9=Q&"A.TLI"6\!+7<6CFG^(D]ZY +MCM+!,>SNOA037(JD?50#O%DMPUNT#(*:$9_53KU%D&;BE:W/79F)K9V$@KBQ +MI)C([VO*=8F6E)H)7JB@A:M(^=DUK\/\3\3$F+N*GX!S'Z7VE1KSVYJ7I B" +M T2$,Z !WD&O]):BB7*$GIZZ#+K&FO?11>WJW=$9BJ7]BD,]ELJYCI*B\Z'Z +ME^7 IU(P0T>K!8ASI_SV8G0;I_+9)BP2!YCP +MD9":$0.(PRK#"9I4@!^.F8+3#70Y,#SZ2KIP6OBU]XB#:;>#!\U%/"^B I2B +M7+*]0):3V?+')G;%&HN%D+U:B(>:DT_9DO4[_ .&FGJ"FI/ZII68U\*L[B[O +MX8=%G[Y4OXNM1C>9)\P$S4OKG!>.E$0\OX22EK*0T.JPD3]?+V+G&X0_>=7IERJ,'?S^"5 +MB!X=A)D%)4M!-3K:.V6Q$)BN @_9SFB[1D/%P,F_:G8J;KYYWJYO1+L_6AZ&V!9."O$-SZ_7& +ML#)"A+&BKYW7?JB3GX]PW=#B7IQ2O( WUYE(LI+AZ\;^==D(JI;AUP(GEGI? +MJ-GT-3>2YTM0^)-[NUPR]I7LZF-F.D:G@Q8NK(*8J\^DO9+,U:L?)O+6NU^6 +MC(<854> #'K!WB[Z-"[BO9B>@SN$DUJFLD2J]_P*)T;2R?;)TH>8@(&0@WI* +M29* S93'5?_T6ZW<5(W?\JN7$8;NX8BV/JE679IXS3)4_<#VCK^D4GR/B8*= +MI9""Y,.EU%^ ]JV. JJJJEY102O?$,7IUCF.N+.^BIB2_[Z'_K;'YHJ=O_A6 +MN9*6=]"\R/'Y;AO$TS\4>DQ9C8U&L#JK@LK\R43S$\] %F@7NKR=0X:SQ\(P +MD#?%K[J<>(%:IXM>"Z&6JZH #J^#NT]2_B)8% +M==SZ@L9?NO>[U>;6Q=2 EZ&ZNH:'GE%, NHU\)X(Y]*2-PF*]EJ11>7R=3?5 +M\,-OE[V=EJYAB6"DN2S*CL%&U1Q?IX?!C*P-2Z&5_\%ZM-;EYD$9N/R1C%R3 +MJYF3IK;8POS1!@J+S_9C?+V;@9N2J'.20YT@YL;V?O8BF+96&9I=&G\55PMF +MA(B3D)>8J[,-]#UT']?.NJ**1[:*LOZT1X,!6<#6C)!>1*0=RD%@FO_:^^;G +M]<+VS="MLO*OCOH I:/R,1?N0XJRI$E+GIZ5FX##/GGVX-#'3X:$/(FLSH>Y +MDC_+ 8Z3SLNV382'BKM,2;MSCE^-<>'BF^?CU>"T#B; +MDL&DD,JS].[2YB&T4G);AAR#J4WCBT6828H%D$JH?W&6],?W]@N>B9.1-X"" +MD+0V4LD#KL#^$ JLH_T;F6RV0N*:]71FKO!GGJ K7$*3IA6DQ]Y6DM?50J:6 +M>]ZM6EZ:G&N4)T=^$ %JKA 10+7ER/YJR\AKFB5P'" +M]II0K *3WDVSK)2IC(.AAIW9Z'HA@X7^P)F3GJM;J ^;_%*DGJT!$'&6^C6% +ME'04J=ZS_ZC@S/"3VHO[KYN(^9[2U/74NM!'^*/2A-I7@EZ"IGOA^0[=WZ8Q +MK=ZQ0EVAI9_A(KG /J"?GIVMOIB S@-8XC,VFN8*KYH$B[F$ +M@MATJ:>HV-7KURX2_J+42\AY\MNPGKN*N).W3<;!;_/WPHFQFGW4L7Z7PJM; +M3Q+8[!;!S[S +M[?8%-HB/D%J#CY00N(6@X!$W]>]+592I5HB'GZ-8$_XU%CI_P,T>?YB7L@EH +MJ W6R0_NVO3U&<*6A[_75>V+HI>;\_[U\#9&X(B^G:""=M#>TJ $6(T-RXJJ +MR\%!F*O^F5&[OD&80LIV8E]3#Y].1D$&M5:?^LT?J +M)SK%L]JNAE^0LA=[NTV&DL<,RM:\T%.-4%RSJ7A'JJC!M?3'RQ.+5J!7";BK +MOI,\P7+U]/?+B\:@@)Q''J23C.6S]2_N]N4>M;S,3YR$@SBRB,'5Q(3U ,&) +MEE^!EYY+4,9^@(CT]V;U]@.M7HUSB)^*LE'!IIW0PO@G RP_(D72$I:N7F1FQH8Z):?[YU#K^ +M IQ3T[E&43.1PHL'T[CP6AZ 0O:0\,;%0KOV HB((927D7RMPMN2Q://M'HV +M%+BD01H]MI8.P?OMQCX#YDJ6K*JHN5^>=X^%*FRR[\5#5B1:NJC\OO4*67OQ +M1Y)RH)Z@1\"&FYZHS%*:]]W/R-_Q,)?R.M2_'8F-+)!8R)O$U_HFVUF.L??9 +M_NM#F9#W^(E&:N7&>M[G5D<$^WM^5A**"I2-F.$PQJ_^%=*L4Y_[5O2^0O+[ +M!V94PS(S8/K:C79DGJJ3J(^5K=KSRRB_\#V-.77W@5M1ICUEH2=*HJHC_J@R@A% +M2%&M\N)M7X6+6(_/?$*B]X+K:J:VML0:^I"PGI(0FH/ JL58?8B7G195+ZK- +M\>W@^CWCE;P1\5>PFJO@IEL#*V?;D9/47T:=EE= 5%W9TMU<$Z;V6- A@IJ" +MDA7RBG$R_336B,. 8)*#V1N&!:P!PO3ZU?(2O[Z<5\KX[5,ACIW*S=?Y7=J8 +MBQ>,[ZD5CHJH3ZK1,\3S\% #1])&9SXIUW3,ZA+W]CXP)52\VJN5 +MB/;SP%.+!=T#286<-E4]B;F)1O"/I_0M/C_#";J&)*FR"+6@(*?E>=-P5L.* +MI[F*_D"6EJ*4V//D\#;_\HR&5^#/Q$$)Z/?3.:JLA(*V,I"*@ZQ=U\,Z,2[M +MVJ:<$%).IO";LL?\RN"%HZ(=18"[@=J2Q)7P1>54MHJVAB":G_I:"PSM#]&* +MG%&[]J>2F:R.2UO^$78OTK@/AY/#>@*2%;J]Y?F5(."@BPX@>HH[+":BE=K@ +M.;0VYO5FGAI,9KB) ZP]JT7.%2CO@]1&MEV 'Q6,B,*Z_P+FE_OR) <-A?M* +MV@Q;DXI&%:O9!, E+@K* P*;>E"2C%O/JDHIFH$A_F3$Q;_&E+#+L:60K'D9 +M*\_D7HBB]7"A?(K7%[SRQ^Q+<;"3^3!;>@\AEI,;#\7P7[!+G7:;0G]LGJN1 +M^I>OP,5<2;9P HB*C]1!3=#RQ>P0 ,MUDD":0W[P@Z'!<>TF[F7+KZ)059]% +MG*DAFYL*W LA%L4^( +M)LH(#HG("H?=@:R>F4""N+>31-+LUA#MY5!85%&02(H#P<*O\9F+H=26F8(" +M\O+Y]BZET=>0E%VTUUA:H/*6VP,*V%2;WI&5V('_0*:JX1*=[Y9B^ K7D%B6 +MJ)H&5:GPT#"0.H"=0*9>D(MR&_.\\L)%-N[MSXT$""J&ADE+,II7 ,[[!*7: +M\LRWF@9/K;FG.;(O*1+EQG;@P6FJCIE*A8V\0::'FT$#JA?1CBLNVKL._55: +MGFJ GI/0>/';N47D8-'5M(J=!=&V?\W9PM.=AK*[U9""K\UB;/3 +\*$6!'\ +MFD&"KKFD5LT% -)_D)@&MA2OQ@*ZD$>7B89-TJR:&QD.?Q'+RO&'=':-B7V%7KI7 +MFR?3[\06/MNYFM"#.)^1B98PFO\E!^[A+@O$]WQ"KHF? B>+J8+#E)[,TOG +M=9/!6 &25I"Q7/T91,'!A;!;N9!;BG+8\_/V0C$^8 ;JV6YO8\G[2/?[!BIB= +M2)J<:ZF7[(Y[P\:IP\S-Z\,!ZHNQBI[&"8RAIE*^Y[CY;CYRCTI1@JR7@+XI +MP8VB]EJ+AJVR1/JW#;;'-]KURX>E^85:5YY8P!:74,M3580 DY\WE5>)<%:_ +M()Y=GNV"UEJ08X-;C9A:N(1(Z]$>)@'/6XB:W$B,L[&, >HYD!#DP5>5K*&I +MFX5JHYY[",0&VM[ FX6D#$&)5YR+$;N8@[&7+]8[PH=]MU$:=&>Z7C1:G2?+ +MZ:\*S^_OX$B5K94<6J]<-( 6 L>K[/00[,56 ";4J"^J\3,X0A4"G9=CG"_ +M@ZE8W78@+L??\%3TDI*:5S*T00+YT=:=HJ*579FKEJ 7M\ +MRM&KGG:EI9(!JR('J\>V.=Y4K<]+E_:?7%7"D[>HDOD+S]C7!LL0\P&(JYRQ +M^E92J+)CH C8\C%_QBX(G$A3\;*!7EK PJ'D+H9^6;"(^D'AWO:B,/K@M+:> +MCUH509.0?ZMBSZ?$6%R:?H^7NAZKMZT4].;>)-KE +MQ8JGJ8W9B(V0Q:H JD5$QA_/3([$%%2M@9*L) -3)@9N0 +MFECQ,?7OT/W"DU71$I.:NUP+L]:7TPV!ZL'+BPOQJX7=FI:T1ZJ4@-Y7:1OG +M\# 663R"DYU0=;J=QX]S/9 (,G7 <7F[<2HVYG9OZKKVH%[P2Y97H'!"YPRC +MV%P001;^O>$&YIIZ9P4#)!=70V8^#C$&NB*R'HY36QV'LU=WWT]*< +MK8>NGJG8^>&GBQC=G)'#K]^NV%N8&;::E::"GI&.>L'JXS?MP-"^$(N5CE%2 +MJ-'#H+&^<(I;@A%_C>?4UMOMU\>?LE1Q=I.NUZ1.*Q/.K_A=N%I_CI6)J4.< +MB/$J9:#G ZS3\T0N4:5^\5E_%7N +M29. DTR0>\35Z_K%!<@/GDQ%S*_%7J"@%^%ITQ8F[N-0LKV@EH^(V)"3E$"M +M"JP+XP''QT/O#G^?2OZ-FI[H!AW9$A'WOE0/+D:QG5?36D/%70/)O8A>K9Q1 +M6:[C*]#PYCY1F%":4;Y5>Y=@FXMQ:H];A\B"4+11G%U!EX'%-O4R/O#82)HP +MG5.]^(6%Q<+P[/(L&U-:D$M^:I:7HI0E.F5MD\;+9J.>6$.>[,?LFJO-SBS/ +M ^'' =\GD%^>7=6ZQ+MZBZ& 4L?V +M/,;2YF".O9^5^C58_H4*[MR0&?J/MX>?^P5 Y.)#\@?%DXN$II*OJ/BV4-C# +MP=)>@J)%&Y+ZJJQ:4?*K\^8UIO&K6CB_%Y&^I:-,0_1TT.WU4J9H0UZ3WY:3 +M;<3IV.S [\.ZH+B8Z:R]DZ6.N(NGSHDD\>9LWYJ 3RBOKTQ:6(KZUJ(P9 J3 +ME'];@?"C@[BH#GL!'<#!X>N@*_9C1I<75\?HC%.RM;O#/YW4T^R@G!N0B3*= +M6%=QXT_#_(*!G1ZTDKM8GA4^)? *_!&@DK+[3^CRE93F6UF:J)<9KOA3GT#3_I&:]Y3NGU". +M1==>0)BL!:[9S?O,U]+0AY>42(*%C8Q-JK +MX2S%YO71$:=2#OI="ZG>BIS0I:>30/(G$&_F*-85D)WUM9J#26_"XM>2/[R: +MD1^?P_.C=9*SPTRPBHTE_5F788Z)UP_*R# 448R5D).:LGY"Y/OU+F[NT>N/ +MJ!T#N890DIA+$N,_Y!NBE ?FU+"U6>D[O"XB(I1=;%3EZT,XPNWL9Z[4L.J]\S7UQ+$.X=] +MG!>^E:4;J,0G@=*NP-&=M;2-5;>V_Z:BCNTSU]3Z&MR.IGFNS!,J-J-$P>0Q +M^_Z3&Y>M@HA)JX23+\36X2;Z]_"NEEB(BQZA2H::/^G]S,KG(=1LC$2_E+B4 +MD*W;K=DW]-;']O-MA?N?JD1+G':3@%;8PM##XOE8[]9OB)BCC%^:GHI!D(K! +M.^?%[\)RV8:>D(V1<@-0R0+:_-0&U)I35@''(\3F$"_;JHAP6)^1"8-B=_F- +M6J,2!;:@NS>AG)UFE@,-^_G\E^_)F Y'UN,:_586&[F.(3TV? +MES_%EC4@-! /.O2IA9V;C8LD#K?HR*S/\?+ "[N,C$Z25)UR>IC!P-CV\'78 +MBI@EZ, 6,+U/O8R)TRD +MGX2/-YWHNZ:=4\PLWXKBT8F7O$ /KY43:+23@-[%;^Y:6H"6]K[3ODMR7D&F +M&\&H"NZA38[#R)E648B9EIVN%ZB/C\'^Q_)SY_$ND*![CX-<6RS/!4*>UIZ% +ME:">GIB3E-9_QHOY?J^!WVZ +MGC""J!C8EE]%A>/%_[;;B5YL6)N'FY92@*CQN7?Z\D;7%Y =HOX B,;/K^T +MU (!\P/.MA7L5?KLN*Q5NLCYYIY +87"EZNPV[:);NAN@SY<#PBT[[=:!4!6AO(81VBG'#O$V>I&QD8Y16H/PX.%%U[;7 +M][:^!9JCG(J@7XK'')/F5=#0"521JENHL%[''O4N5M#P.H[@$I:#]&J;JFE9OQ#M8#].$23WYX5&^> +MO^BLD@O,LNS3[]9W3_Z?2YN>6?ZZJ!8I6:9YQ0ZFJ0[<$TR,L9^2D7):;"13 +M25#VE_ON\)6)H(D0BJF3 M2CPH0+DZMR18*)]W#FEO7MT4J!@964(JJ=^8^X +MH)IZ?C^1,KJS)["6;&NW/XO;:T*^0GF"?K&&3LI1:PN2UE]8R +MTIV-K5Z7MZTKMC'46MGZ$-7)0JO6\IM:F3BIQKBJ=/OV3\'BE/X^U-N<"%ZW +M2OA45R==D(#T"Z(Q%CN6 +MN99V0]FR=J_M\UP FB9:FKJ'O8M H/Z=]<+%480V+WJ-FI"0[,%I]K/T=>., +MDM_HEWQ9B3JZ#4T%_(XA!3 7LIJ!C+CAJ+@&J8WJD1)21:<(N]4BD):*GD*$ +M>X,!SY#?P1;2P].#4JMRG(Z+C+^YG]E(\NT>D"W;3"&2A(8)D__RQ0/(BG61 +MFU^7&9C@\_CR\'"KW[:3A(13L[JEMGK,@]K$FEF4N;I14?JDGGU$\/D^>]?+ +MJH^VNPQM?X8?)N=^126O@-#62'^+GYA6LT_9=!$^-G[UO7()G(*.7NJL5IK! +M#HPMKL/1[HX%O!R2+8JL$%L#U//V;:Q+O08K5II6BOZB1I 7VLY-]P'GKN#0 +M*9)1,K:.4MNV+ Z6Q2OT\&80V_VCLEZUB)ROB-W2X89SN'M0$:NS&S/M]^?T +M+Y63@YU?@5B*JEVKV/]'7%&\4KU66JH#JA>#I^O6L/330$\5L=.,P[6D2I^D +M\.5F?L*8]K&XOD:'EO/L$NOVUM;LSHZ0?KV$F+R3,L) @MP &G4%0X^:1:B/ +MG\T+ME92P>/Q-L8V08N'](N,^EJJE*9SBR"L0O? #T\*X$-2MYM\=B^R0GCW +MO5#S\=1P,.6LH]0;6Z"KJ4T7HP!,G8FH4JFZ +M@D"6%Y.;DHCR/J)OP./'I:.8FHJ.F_<-\,+U'<8"K8_&FY:' +M4HZ#.HUR5VXR!/@%KJ7YY?TZR&0L7S[N8Z +MW?# '/C']ND_^G4(Q13K?F_DE>'2E:LIYD8P>W5K,0E=-!; +ML;N0GIK+QJ,VA'8"AK>:JE,BEO'F0_OG!_&FL82PG)NVGX+-!_48G';_B5N@ +MNGNJ?YO!>]'O]@,PB]N@ UIOBI;S3!L;\77ZP+L&()?(27)66IH!8?;&EM/* +MAX:L1*NN7IF[C;\2W8#B7L\9OX1QG$-2@*Z1TJO2\C3V$MI)BH91=9XF&QIT +M$%.7S*SX$]S6JX\4POI"7@6^<8*XQWG#'+V@ +M"G%:H5I]'C+J:.J^5BL_U%/?@W\5MAZ(3DY+_AG*J ^O%M]7B"QV3NIV^EZF.H9Z* +MU:G4UJ3K8;NZFJA"B)?-@Y[72/*]4E03T)E*?55:WHJV4GF?@P%"S-=-P]H@ +MF8BN!3*IMXF[D+AT4<<6QR[>4"E_]H*QD(*ZGT<74MA0-/*%3EW#OP'@-9W% +M[<*JE(*%I?2[G[C.5]?OQ1B&N &%7%%:$W %JQ,BR'/:AEY;)!O,3D9!PC*!4@E*%TB=OEKX77%W"O9*RNXNL +MWH':C,[*F$.2NW8"B=^039U2XC\4$/&02I )J_R"F$X*KL3B-\1U\UJ I),P +M/ZY;E4W#%[7_W9>!J[.:C$^5OU,2=/_-3(XNH<5$#(ZIE,V&F4UJAE+7(E3G +M]?_+O9_;BHX&8HFC@!(-]>C\T0'9"AL1IH>-F9:.1UZ)QEN;!2HG\!+^Q9&] +MGE_279I7H6M:X$6(D;"0B*Z7 )KXMG_6 IJ@%)5:H7HZLG(=)4;:G/K4$OO. +M 4)#>E"7&+34^M+8\+BGQ +3PI*.$HY;\O,N.B_:G+B;BF*OM?J'X?(YEY?N +M"X,4G,FYNF%(N#:>H:14 DJ(R(>F6@&"GD"+.'*H\-'M%I9WR)F'AWZ#D$T7 +MMF+0&^+8[/3>%NO#"9"5D?::L&N"FZQ: M'Q^>#R$,-YD:&M4L7ZE_%&VS10 +MH8N>W/21M]-VQ9>UM>/\4DH%#8JK@X1.60=+!THOG/ZTDJ/8OZ);@<<>,.^: +MX]*1L*0;@ZN'GDBDA?#Q[C/3CUIXG7F[5:*SED/[L7?E]--7!86J;Z@%4L.@ +MB<%(WE^BJM1O1%B(0IV^V, =@N$T-O[VUX_MEBZ9%Y:M&!I,5=T"S,!"G$G1 +M\/ 2K$6+3X/MJEN@=[W!\GSB,O 'E)"@#Y!9UZCQQR_RA%Q3V98@OZ\8\>3D +M\) +CY*+KO90J).FIZ_'_<>P3*._GY7#K(*LMYO3,_]5L!KUBT+&$XCCGE"% +M1 SC[/;EYPBF8D*RNMV^BQY"PI4E__YU1Q#:;$Z.2+N#I;[BU]1X!T*TCKR' +MX(NZO6NCEE?-Z]3\VO7S3861F,O4C?N_K,2[I]WX$JS4H,5@31R%EZK2Z,H7 +MDY./TIZ3%COFXPBRD'U0EY"_ Q4 PE 6"D7>E5.]Q\&_U>; Q^CMH[[HIR3 +MJ9J?T<[*])1"E%B6N)X3;9"K43+ETMQ%MN<0,+?<2QAZ7Z" _^SP\@^!IX)? +M*I]E,"U64$ ,CI7)MK"8ZK)E +M5<*OCX\NO5"KMAN*4*N/^*/=R@% OS)X^U3GX".^CB6>J.%^O#J[._>=NJ5 +MG;.=VY"6'O+^X]RLMO1'\J**@M?J1?_ZE8_>&$2MM?=3G89UMT=LJ]*)EA)? +MAA*;@JSWFO<3T7WWQ<92M*F:^XJ&7)+ X^I#M<9#D_!JKQ/'?::@G^&6[700 +M%.*O%X67OQ^KO3@GJ5G=W(YG"N OMX6 O)>!AJR?G?,6'T77_]M)+)"3B[*3 +M-HNPT)LG2-)![ @#P_ !7,2PJ99)4Z+F!H#-Y.TFQ\#;7XNCCUI8D[J- Z;# +MO;83CQN0BIC9XZ42QN?#4%B^&[6EMDNP\(+E5_,0';!+O/J7_'^(4+OEZO$N +M[\4V;49&PZI*C%Z3'ZOK[1HV\XD.NDBKDI^FD(C-_^[ZQ_1.@I67K\LHKKJL +M<$L(JBP+Y/$::XR/E+U?G8MFMA$)$+7P+9XIII)&PY:7NZF7H+: P8I: ^SB +MR^,".Y(I4UR"0_JB8!6NR>/%Q>WV#_RED:Z.L+N7K0[ X+I=@$4"LKG](OXP +M]#3%A5QV<9&F77NHJY[["R3O";@2BZN,L9J;)EI#663U]]+ P"L6H)B6GPCW +MLXS:VL7EK@.+7ZA_DH"NEG\%]^K9U_;RRHUZ5;_/F$N[8EN!B4RMAX2GT9\ +MGD2)6BVZD*:+030QY;(ZYQL,K*-8RGN]FCROVX\\FIG-*_9H2=NPW$ +M??;[M/-#7XZ3BO7/0\NX5)N-'=/'UZ_KQ?:&AIZ:G)7'5O^@VGCI_L5O@?V-^^P1P]>^IVL0]8/GX"A-Y75 +MT& FOJ.07$S(;8MXA9<)+-3.(>#:1590C%5:0+MX]GK!LCGPU_)&TY^%BUFC +MIU^2(9Y]"8[+X=K=Y\#FC_.1=Y["NY'2>:!7V.)!\N_VQ[^CFHW>0JJ= OS. +M\GZ)DYVUH5[RI7KL]\74"KF3MENF=SI^N9*]9?GSR(29T;N7U(NX@IRHX39S +MY="+6I.[D8#V1OA;FV0#%C7%]^.O3FJ[6X>'D)#MB<;3/\601\F:^*RCE)ZO +M:9VI&P_\0ES#R8^4^D#FG8U/H82=0_0TW_;6(T=2U5-:I9&II[I%@L<."Z3L +M^LS/&,==OI,2VA"\5K2[GIFA]>P2VH>,49*%\%V[]M*#]='0DCZ1UXD:>5G" +M%1_&$ ^0(%0;6IVL7Y#0?_#90+C]B?!1C#U8BI664R/R-Q 7DU*;6G"H^^J$ +MNE\-P]/E+,7##IN3ETFHKY.# />>_16N%?5E<+KL%JV)8J"7@NG\P.3#PYF, +MG9YDKJZ DJWWD^3J-9?<_]JHQKD2O(>/7A8LI[?JB/OTJ@W[\=:[MZZ@NB93 +MJ[B 7I>BT.Z6>_3S4+944)2*JA=GZ4=1M!)(GOVPJM<(T.4V+!_;7:#?GU07 +MFLBQAM^I#0,P<:6CR()=>K^0E'OMY#74+L7@S89A][J13G^C/?#PV?+UVY*= +MK%=7FP:,6Y7PTY:^>C?0K72/E+E[OH:XCY+RE9W.UL\23Y95C)J_H*J@FHO1 +MP/<2]]!#.WR6DZ^=V/E#R)RB&E%6H:Z;1<8S;L+'PT1&GER2UT.;+!>*R^L)TII" +M]@2PP9:6K/H+P12TQ00[#RIB\G5]8=HG"=$16EPS^M<60%O.Z<$@]5C";@R%? +MP<.YH!YQO%"KJ(G"7)66E@5Z4X>=#A"+K:.0?]'7<,F$UE"[&Z%V2?&,70TQ +M\3?<\/:.D^V"]I.VI@L,&>/%L.V*N*:X75.-!XZ3G C#]S_UPL,75E6$KU^- +MQK!WRUD$),@+T32#\EY*@X9!27GR4J#>^31NY,B+>@U0@Y"3").IFM+W_^X* +M^ASXE1"2^IV?^Z:KNG*@1%WQP?CT%O3%1;.+D=*1]MOG U4*-)2SW;:1FYL5 +M(G,6]O9CO(.PO9:7VX.FG_=!SR=AF+12O9;QOC_B6I[!Z?'T;]-8CZ80@Y)' +MLEJ2I=#V-)HZSXB7EKB"4W^.F8_8U!DUY!3S:8"\A[R:.)*6A@#!_.W.+]CT +MKXV%J*Z:E1.X&I?7(\3 U9)EAUR8@H!TBPA^D"!S -W('/C5 4,UA[Z-L+*V +M"7[^B+)=\O1YTGXPRPJBOXS\6)./0/D/4GA0GXZ2<9(; >)1)!;$$TR;T F2 +ME9.?J/*7F:GJQ%^AFO%UB5R;;'V_HSXNG:;%"DN]P)N6CYR7DHS"T^W"NO6+ +MDI&=JX]65I5J&M;'+]/ $XZ6F$R/GXV8H+6;P1S.[L[7T(G7JDR#F(V(S9J= +MPQ/%\O2Z][B.7;^L=8-X"&VVE_#*! K5S<[%2:,>_9%:UKE:GZ!TDL'JE>XV +MQ>L,G!F>Q)6ZY=J45@!1IA>+@7IR4\,K[P0% +MH))=CKU6FJ"06W%WQ? VPL#M<"Q#G,N+I$N>S?O9]/O/A].BF9P)AEJA0%D4 +M\W?F9>>\E?F 2[N4BK&5F0KY[.Z!'[UKNJZ64N-D_W-+WY!5GM9V9 +M6H_M&K:XE(NAWOA3S=4OR=6.LA6?TY"JJE+VCZKRO\4@<#8"K%B249H=KE;S +MU\?@68+:ET22R/;%(=4V%M8KKHH>7(;9?+Z05ZK#WL<]J)S+E-!]5[\AE?,, +MZBWV_L\4D)20&[:#1YX2UA'PET8]CZN5H+] DIY;DT3-_CCNL/I#%Z!<;:Z& +MZ4>1DJL2U(;7"?C2 +M"_C\J]C82-QTF_Y2XIX)S!J1!>A%P/8L6_QUHKE6L)H9 +M\=/6FI_&YS>=FX6PG9[#N86]=^G%$ZA1GEV5^KN_M!I*P<+C(]?.U%N-K)O# +M@UJ&]^3"]Z,0I@JO%^2;J)L>3:>OF?(W8_KWP1^VAFKD6NKMD9N >0QY/YV^9.E**VDPF2>?07K,%45@G[D+.>JQK^V^ %W!!17HO87\/")-+OP@%$E@'8 +MD+NL<^*7@TSO!=;PF9.0_J*\6H@:6)'!T_)WCN9ID*Q#6^UXEJ:%R>ID]D3" +MB5N!LH.;7H*RO%GF[,6U[>=-I[Y47I>]IWF@@ W1Q6 R$B+N>/)MFEK;1\>;$+_;S.)YY +M7RB2B+Z*I)N;14W%]MP$P<\6FZN;58O[Z(.+D9"Y*3YU(#?"[H664)&>\*J2 +MQ]3%, Q %IDE]Q.2R. L^O??D*_[PIOPD7J;H->_0(_#RY"$$ZV6D1RS)H7+ +MP?/FT)SO4&N5H'V#KQAVDVK'UAG5^L/ID#F-7+]%]I*J!_+L[_;6\Y:VO.R9 +MG;W+('*"P43=V-W W$F?JI86AY6XQEWZP33U+BRVT,KSFZ>3IHF"4L&R%_'* +M @^JW0P+&(>ZK55V]I*^<0U^Z&?F! MIZ%8.QC\A=Q%G".;IHJ( +M6/+^=*XGQ@:><%9\D%U>K6S0]PM[A3.UEEN.H)&7LTB>6\?RU:_U]5"CE&." +MJ(.?D)*?[<'5+OQSP7+DDQZ-CA8>H"T_MS>S]?&)5I0*OKR%JKB:/2<:_Z_F +MVV.O%IIMK7^MJSB6NL4;[/ PUL,=3=E7"E6]=I&@L('U5L##3,7MXM!;OYR* +MO$20F**-MGK1P?S%L/3%7["T5(V1 9C@QH[6G( 4NU^16%O%-!; /O+6E)Q +M'16Q&[VD3D, J>+@&+!*#YYQY):C%I#V7PL!?GHS\J00H>M2HB06QI219*:P7'X +M]9:6=ZZ9AY2:M:I[ ^DC":I8&]BP)U.+P6NTQ[;OU5RJ&3OC:2II>I)S^3C'.M>!8Q#6HD:AO>HQSOFOL(P6J]& +M!9-8NJ>;G[F6LJ#$T,,$RLP#'>JRA5%ZG(>)ENQ'@Z?!\;WZPAJJE"&OHXN\ +M0R7+0L.LF9.$E]N8F<5PQS+Z[<5=H_1-4A26^9&46,U6VV/Z.@J[A?% ?R"6 +MW1LR,_8VP]F3G[I[B8N?GJ=,0/;UT.#32/>SVY['7?>C $RV7O>+EE95DR* +MIXB^B^@7BM$ #LPBV=Q4L+I/UYB-NHB06PF2.?0F-N*JA(5SNXR-=\9QHDL0 +M@BG'S" 3H;2BUIU36\Q/&A*L$E_!*!W0]_X Q(B:K)8+?[L"CQ,<++">JZ>2 +M@YG+\C_B/.Q%F!:BC5Z(D[F67Y]-#U,3L9.0JWN8J?-@%XB-]M7P)A/R#9N& +MFQF9K%#?O-':;R(WYT]&<-*:DQY=WQ12ZO30%_?JEH^>7+_<3HNX59T#($ . +MW*?DOIKX'H^^U0;,6MOG$O%WY!K"N9;=5;>7BWN!J96RH,_XH^:H^\#\K[V] +M7ZG/BJFV; 73!7+%%\;LR,?4@(>GD7N#PJ/3"8>\BZ]&EY8"U?#M]G8O]X:@ +M]@6:4I.=N' =R:V768IQBY\2"+I(P)K_3=/Y\A8"PX\$;;>^1X2:@8S),\4T +MHV5%DV[C)":B87^SZ;;W8F2O(2^AZ4' +MAO +TNG%_A OVHV6/)#VD&"6H;.UB=FN"&'IS=L%]*V$E=B\IKBNP8&0>,,9 +MU/RZ8 5Z@*.%C@E"B,?[QP&:7+9B,AJ-%V?;LG^#/ PV2G7R-1[3( +M[-%IE77<$,^"FCQ)C9Y+:>R/MP5,ZJCA3_9/3;^,!+NM0I!5D/%K]?JV?]F# +MOY&8K)_+"8F,1EK-K_JOP$CDZO)ME[U>B:>-%D.YAXC'%$;&T#>9D9.*GJ77 +M@HK9%0/CW:(R>W)#EIG)$L;VYJ[1NER?NY;=5JK %9K!"U"24%147+8+F@.5 +MC[GQ=M7G^J4 '0_#W5N8N'*73-C^-Y;Z$P>7K!U!NYV0P4RJX/3R<];3[K2> +M#9N.'4=F<+K8[OJ,]M=<9/JJ5%3-U9J,DEL9\?;%\N^2NYA5BTH635.29%H! +MT(P8!Q[%PJM/$R[0PEYYEAV2!UF?YC2#P/YVFA +$FUZ +MN:J*6]>0EXK'(&SP\G.8G;B9<;J,ME6N&?KY,E R#J*5FFQ%C9N+XZ>K94AN +MS@[8]8>Z3^_CDI2+:9Z:X//6YI8_PP-/ELB,](:IUI/V^,C^:$>!K\7N\$== +MW)&NMH,7RB95TTCSV-:@Q=NV4Y:;GO=(5X'Y3Q&Z&))PEYB>N(X +M5%:>];?06I!$O\/KV-F$%E^%I'*(CHQ$6RO"P3ID\]!(D[A;F;V>ODL-U?'E +M]+_ONW:KDII&NK.9@%DR=Q3&&B*[7Y^\"4?/T;BZVLKZS_Q#"T&<^IJ*C):7 +M4H&V6*#JQI#N\@K-_*^52I)8W@@2?;K)U$FGS,76IG8^=NT7_;PG(V13D+8]&\VQG[K5!B0GO6PN(JJ6AL1 +M+O,!NG8@G1I;5ET@FH'G%C<]YL"P!U:2J?Q+DG>UK!/E$V<3V_ $)#E"$[MQ.?X0]:T2::X@1*L!H+;WBS_MWY//' BVK8,;NOO:59S)).RV\!KND$*"J.NNGM% :9_W-NWOXS]W +MFH /&XRHC:776LX [^JJT[Z&A+WC'I4'*'IRP/+^Y&&!2?E9*>D_G/^PE?\>**@)"_M8B"?WN5J*3$/27"+["[ +MEK:]@8=.L).<22(\Q_X#AUN6?IH0A;*3#,KJ%K?VIL=K5=KL7X8-1R.G@//H +MSZ(&XN/OCZ^NBZV4H( 6TYT%5QL#V)0^%0Z)7E\#.M7_P+N. +MFE0>KYZG2HVRC],"CP,06 /".[2GEAUH-@/LZ!$Z-G'&6I;YJ4 /=::?/-GR +M8S?@\TM&H!^[AU.4@X^A.\SN"M/3O5OP;9V& +MGHMZEK=)0<;Z-_#"C7N>^JKPYYFB8/:+R,( Y*K]RL"YNJB4@WF>1X*VL9"_ +M$V@Y9N7@<*^0EYN/^IFK <\E2'R8HY%6DJF"\=[99.[V UZ 7YU?D8#2LAN] +MPLO%XI;XI![UT/R#D$X3\NO],]0EM;B?DEDKZ)>?E0Q1GCSZU\N2E+F2D&:' +MA9E Y-9M?O;Z0VZ6D>@/G>E(QG:?Q\S Q@?"D9^0$:J&GYR#J9J# _OO[<#R +M&KF'JUM:>KM:GD"05^/"# ?ITL<'' ]WG)-:!ZV?WGF?G0/:Q=96%-M07!I5 +M1AVV*.*?U/;5@Q"?G&!7N8E^MY>4V-8]U_8FNUI&GP*/*Y21;DT2%2WWY<]# +M6ZJZA[_=#6@V@>3WI8 78^)T_*L%9K![I=4HY3 $R;=80!6UWZ9"YDIB0IC(,(ZVUF<_+ +MS P>W\.]A96\3XR.A:F $*[@EG;'K[I:[9B-O<^G 6+IBV(OV@V5*+=(V.; \'SQ@:UWD0)[>(R#V4 U/#_2PZ^@89^:457&"\XB +MTL7VQ]CI7X.96H#>)DKI\3;UE^X^T(FCA(A&FZ^-YDZ7Q50DX]_U$8L4+;V? +M5H'C)/93$I8V]^7Z4.<8B9DIE8U:GGJ.B]%]&?\_KD%\^:5(IQVA>#@:RE +M^.D7&L15B+>;4AB<'4.^6>/0%/*RHA_13<,;V ]6H=:8BS?S)E04HX23UER$"OP;.+?VY1<;U+Z#TH=:01I#=!Y[0-03[BZ0 +MV8:4[)*NJU^'BTI9$YW$,%M"HX2!.X?R?=.*H30NYD;ZP[JF4$P6_82+(K8? +MQWQ S_8.X<:5EE6/$FW8AH2[\3X\QC)[\)"^/I,7I&NIFK)ZF2W]Q/;8_ K! +MUI-3AP&V]$J^)B060PSC_6;DUD5&G$N'AH=)NM++H\/>D%Z,HY$8_\+;W18V +M1_?<$]F]1XB3VN& ER4<\M+>]EI$O[#WN,9/BUB2\\;_PQ2'D'236N\&I9*- +MQ2GU->7%2J2DGI^2J)H?/LSQ[/8T):B+4L6^;[A-NW.[^]'4_-@FPM!>M?R\ +M3XV,AX(.DL3S[;I%OEB#5ER N)>HCE>0=KTAR.F/J,)8 - Y>HRPK(8ZJJ*Q +MC$B%/C,T\!:E?).R57)2JAW YL+CCZ99KI80@[CQP<;NXM/%5?"P7PZA')*@ +M5'W;RQ""M=#!E]6EF]BLI%V8D_40_<]A[59B6W?/1J>2BA%Q]KOZB.LGIGVV +MFZQRGTG0Z^TZEG!Q;J2^1KZ_E(JXI%/JB/WXPY'2EX(%G8F3G5-LAI^2L_;^ +M5^_#IQ>9VTP&4JN3I9 !U\VH%,7"#X\QNUX50*F:HIQ9K!W7 3O\EA?UIIQP +M4:T 2:H]PPM%X;B4]@:F6X/_"7 9[/J0(1S4&JRGHIQZH-^=)^*F\!6&D9:? +MD99.P%8#2/3TTO?8X:UP1E.Q7DD"KK)6*V,[-SG;Q'"T"A8I.DKV"I/+8VSNU%^^2$U%XD0/\7DN7 +MDF*EVL+]RJ?H$\#GR*J*'Z62>@]^0F!: P50+,+7L!OWU/*QP'.[D\EJRS20 +M!!XKG;&[K8#R53+F.D+00+.;7*48N62_^L"*XN):I9:1-X>)F6V44Z/9[6[F +MVS&/4$R"L=L^1%2LFIL*V\0YB@DZVEDMOFM.WV=D*3J*\5@J22F8*1CGCC+>KDZ=U' +M:L@15;BSUHQOJ*&@DHK9XF;6]E/E#;1+J9;4FEW"_Z/2=! !K9Y4FHM:\_?0 +M+-;1O9/R+I>BFXCKCA<(SL#9A*3&"492V;^Y@)N$X[,^+?#8B/K[OQ^*C982 +ME-CC_[?R0[Q[HNC!=,/7X/?C;YI01$,2A9*IEJO-#'K8W"<4G)"M +MC:(_AH[WBQ\7FQ\(!BU0(*^ +ME/"?QW_/&'RF2YR.TX*]899:V5/$D.:ORYU/DXB/AQ>22Y7,]#<7[_&G$JP" +MJ*BNI*%M\\3&K[K^4ZV0$8RBF#BI=/.+V?W,U\?NU$.3JF2+KXD/K Z3TSHE +MNKH?SY"8GK&O_[J#BZJ. ('X^<,'^_\/W*EW^Y*)IDM2N*1>D]"0U/[F-I,% +MB8NTC9*KJP.O4]P:H;.'7_*"G:5KQ.W&^^4<7%*$E9.>NJ >J,+O]YRTB=ZM +M$(GY@S.:G2B08]OL4KSMFJV;*HM.-8642/*1O"X#$5!-FW^]#MVS:L7V]/?P +M9\6#2<4# +MG:!;FZ2)?Y?1$!5ME]/:AE&@10.7>H"H=%KS+LM06'7:488T]IZ-EZB1%#7F +M-B.P@U>@O;*"E91^AL>^Q930VY".E9:+DH>%V8@7L]5&]BXA'UN8:.^2H5M# +MDC[J[-@.)";(CYZ4E-:?E(NVG:V ^G7G[E(2NMA=GP./J7NCDG*=Q,H.]2HJ +MF_72:FWLI8#"7_XP#;&VMY:^I64<8.) 5\"L*^4GE^&71N3\RHE +M?(X#T0/'% J(M%O_B?Q];8Y)S3_Y5/9:XF?6:*BJAU;> +MBI1:P^7Z^DE>ZT\Q^!O#+$K]6 +M7,:?'"LFJ9?:P-03QO9ORPU6FU^:MY_V2,Q4B\3^Y,2MRP8#$[J?E7]<58\3 +MN[CSJ.34;91VM<+=H%&TEB5;@Z+"V[9\$%.'=;R[@Z#"+1:0]^]46%H4MAV< +M.I&@20FL\1*0H;*56Y.\TVQ:FQCB.,3 UQ"K=&2_]D.^SD=J!^CNK?I"HU[L +M2*J.CD#70-/JT)3_[_"[5X^\1IAKJZ&;@R??UD[""\)K5=>43YR!9J.FC0SR +MX1_PU,>'5IN(ED^^D-YPOY+2U<@75@K%]1RXKE[S7@6[BY@F<-MMGF_B6L3) +M?HF>7(:=J@/M"R\V1Y/^1KYPK%;2\.7WP-9SC:(2GZ 56XJMII['UV;!Q89R +MD:.*^OZ0A9/:L;;P].#:A[>DMU*9N ^+'@L^<._MPS]48)U867)7DKW!Z]7O +MM9?*KX^-C8F\JVJBI'LE*%>"WZ, 3(^$C9M7GVJP3Y_!'G-@$I#KGIY?HYZU +MJ=F3[ ^:\OS[[LI*[LOPK9X%"/B;CQCR+$2-4\/A;L VY9GYWD5V4IB-$0_" +MXYGVMMVEH9B?X6HF_N;V6U6P&9Z:%1JZX'7_36D!TGJ!VD:F65"3.X[=Q30W +M^_#%&%*V>8]7AP>WTH3-*,$F/\_(I&!:JKJ2,@.\$93Y;_KT#[G4NF0,\KT3 +M.;^:I\#4H@H/$)Z.3%6*GLTZP\Y*YW[A\,+>&UN+G[,HC+J6"L&=M_$'K@M& +M#02KRFJ;G=NN7KM;H8&7DP3^.:XV/\#1M!A%1[6*^<'6PK)=@Z:OEAW\ Q?: +M.38;[F=1H%[[LY$9VH"GEP,.SQ*L5+0ISYU>_K1: L$^&3_@%="-1H/[?HO> +ME9>ET;'T[O6BJ)W"=IF;FJ2)2-+T[L+$,\;NAM6-B9>4BKHUEQG:@ P=HM 4 +MIEKHZ5*+8[".32BS]/3P-"N CX7!7@:[N_Y$M%T3%.#JRB*@<1")%EN#FI^' +MFA>Z4']!ZFSV(/(#?)G6D;97DYM"W?6'UN3A)W* +MZN7^!>+ OX8#OSIK1=&ZIBMUMQ7JTQ)QE?ZP,#L_O;N +M)40<2D2Z49H"TL2EPYS0FIZ.@*J2P3[\T/I%]Y"@D8VV5YJ[>E:RTPU0T800 +M5IM:45I=;*)7YQ03__(3XIVWDIJKNWQSL3K9]&% >_.'5B69FKV8E+"_S2+Y +M;.(N R2VF:>>G$5*LY6:\P0,:M?#'(N5CYQNVXF[A)^JZ233U[WN(VK?C5M# +MCKBWB+&.4H$/R_=Z! %0M,L]O:*ZEIC27F)^6\'CYL9EU^>8S[L%45EZ=7@B>F*6^B\E_(LB&T9X<^E2"6JQ.LL7J +MK,8?]M*3H&P#BXU>&XJ\[<'5(##S4)83@MN3D@QWA*%!E/_%^L"CLMP9C)(, +MOVQZ6L+ _'XI.4FEZ5RH9=3N3WC>$Z)Q(E]:BC4["@F[9-FX)XCH,'!,A= +M7LOJ%>"KKHE*F9I+3J&CT)FJ_N5ZTCO"KI6+^UPW2'K1+<[;G))V>Z1 EY?! +MD]-T/_ KG)V4K[912GN@4$F3AZ#;G/92/*8=*'F@59WCE&WR.LK=D*)MDY:3 +MDEI[C #1L3?EVIND@JJYA]9,D>IE:.S2>L#3UI:5C"*8GX/@D(O-W^BH0 /= +MF8"\'FU8B:V1]YT#'O__K]H%2).9L=J06+Y#NKH/0?[!X=7\$\?3ZI^5RQHF +M[?:+DYI!P\/G/C[E\8QT6AT$>7Q:U0SWV)!1B?[RB?NK\SIF]9?\C[V<@9&D +MPH""RK[9VN+9R8>06YLD$9S>N(YQ03+36D+0\+ORIIJ"ZI*/EVP9ZC-EX-*" +M\K@8_&^4A%D, SOM[I1V KF?O$!6AH]-J%>7)\HJS>I/0NM?K8ZI +M)2/QM#6UAPM/AK;VI)&^/J:/B<#?[$<-V^G3RBNFFG=#]'+'O% +M?IN9%IX@E%KRULOCU"C/HM([CO]U>J!#4E;Q@)C%^>;$%,73^HF4\:)TJA;0 +MR_,"OMR41II(T'\!/C\TUA##E%"!WO97FIUYEOL0RQ?0E)B;E5^Q&IBG4*<9 ?2 +MK(# IHB:B!A7P,]3HY.&C9F-CY.XAI$%U!D^;A+(B).IE5Y2JI)0.)JY QN: +M8?Q\V\ZT2YZ? 9[UZTH2H)*7*)[1K_;V&XX0VZ\0D9.7\>_0D)!#H8>%DW)[ +MT?!Y/N9MPKR!BZ]&21*70:*:S5VKY;Q1DM%?G5S;:X29P/;#.C7U] M>N:EZ +MF)I?H^[)\?3B>IO-):N96XJX:F%J>G<&M1EY_@3OGQF(VX)K_G2%:=H4\4,@L!JU'I($40+'5%O?S +MG79FKTO+DG>5EAKT%_> 1&6GEA O8>[N.RFW:LFY)2OKFPPD7]U. 4]F9"4)Q3DXFE\9:8 +M\P_C1!264YR3MUA#S3/%+K RHQ!&@YG22)./;':I"WL+YG2#G_R6D=R?D?>2 +MP??L]9>GXFVFH9L>6P>V18SSY].7]\N[D.:95^J+@I%&#?[U/OOFVXF;G$&? +M$E6_H_+[(0HD_\K/ [LF^81&AZU&H$^7T,3UE>;ZY5*($9E\H(*ZM+&F^_?M +MSL\(5L/:R:]&>*>.$@**EFRVER+6;_#TQ Z?W%:?@H4:6L#YPL*-@*"'IE%; +MJ/?&^3HT,D#^D8I96J-^F6+ +MFZJJCJ".2.KS[C?&C86(&K.9NE(!*-+-W _B +MHLF_%GC@O_VNAI(7O1#@V7NZ],N'2(^ E@:]KIZF58-)3='#U<34U0GG\K>^ +MDZ7+FEIXC+;E>O7^9CKRG*/RGW"W<\+9RW,0A(:2A9+TFZK9\E5O]_90U9!6 +MOW"#CYJ@^X$IZ='(BI22U/HU'*NYEGUG\\;\/J+0:YJX,IN2AY7SF-K2<);7 +MRZVFP;^*0W>R7M0MU\4G[_ CBQI03BQH-*S@">OH.N%ZOS +MI9< P\3[[N;W1K9[5T(0AKQ2>Z1:\M? =5Z:\E6#TL;%;N;/-D.VQ$M:;Y.VLIP(]\4P^J-=M+ 9K$=7T)Z> +M6RIL]]0P&P]PF8CM6X;KD%6#&6K8!J80ME2GO;Y5$D6=H#6"\?XXU^[_]IB. +MOQ"3CXE*F^)>?U'?R\\4Y>90(N! +MJH<# -S1EO&5\+V?LMF0;._2%$^\EH0=E:27WV" 6L',QM)>B%>=^K"3O[.% +M^L$4GQ(FA;R=%!8;DB\/FH,-P?G%\D/O4Z"AF9R)59YRC!#JX<7'[]574E1* +MI(J'B+GT?MM<' W*]MP/D#ZAHTRORY!?@\,Z$.06VO.KEE&0F+N&F]Y@1E<# +MJM'C7-]")IQ3BYT0J R^FO;AI9OR\?:BGN7OFH)2732'>AMRJ^- >DF:!?:' +M6(KR]K[OUM?U=YA?D*)2WIMD!@O-'L[PNA9#BU>2\8N0)E?'UL7EUA+_3605XM/IKB^2)X6D(G3/OC&^_;5SYY>BK^=GLOX7E,L_-A( +MS^*6GU9?E8U604+H-D+E?NS\]^?%O[7$AUN/D4^+H'NJF0[(H0'!S4#&B_[? +M$((,NYHR<9_1 L#U-?X_UUV DD'G' +M]O"9EFA7*%N83;6.VO+E_O7"P6O6JHH)F(Z->(X8S=_@U\K3"ZU]C!^6QEWK +MAI!0S69EGFWPHHM2G)=7I*U\H:S6")&CZ!\%UMPAN^\@B+JTU=P+&LECZO<)>+DL$3[>8:^]DUEG.1C**"FT.UJ0TB +MD1"*H\F38VE +MTEORSQ'P6E9031"7LY$'._$@=93'6EP;KYJ=T+F0)ZD#Q.;<,%V+O873LJB@ +MFY-SJ]3?UL+"1X^AJ*J[E%)*B,GJ9?7PXL=:,'VXAQI$LY_)-\=PQ?!SETVX +M#+[&#H>-EKL3V@H"2M/\GU"6N+L7C4-Y\ZKQ8MF64$6BPJB$GJF66IB+N:6H +MQ5[84Z#+7L+8ZL^\BON6./^:+%_941(\Q-HOPQC3LX2?D5N)(PL'" 1P"AR' +MN+R]96H\QC VTIR3FZT025J];).ZQU=:T9P05DF.%?*_N8^K IYX__Y/<$ZF +MN8U64,Y;GS_%P^7V+ME#I9&/VHL/E9CO@V+VNYZB]TOVD(^_6F] +MG56HIJN6I"0647%D__02[]-<0!2M4+-*.P>"]4NN>Y11AIGXF<6I3?F,%'0-R$@Y95D$>I@I.:7P4J-/8GHYS I")2JX*N=!.?R^ M +M._OBB_!&JJ@-&!1#G-JJU.?^-<4+CM6F0PQO:+&WJ<'-B@/)OEKYLA7NM +M"Z"%W<#RL3;TY$#KQY&3EYY(@K/$EGKE)E&&_ ?.]U62F(T%K)>/N%K$#Y<) +MY-C:Q<7"A$2CA9.72JE5PRC(C9R*K9K;EBN,W^/2\#X'A%"?E[255X,UEJB@ +MIRMTG_!3AHV5%XMFCY?5M-%R,_?QD(YYL)!3+J !;_+2\3>0RXKWH-.KOZJ0 +MT0WG$9V:ME %GW90E&SRO4*RWAWD_M1>IO&SHPZ>U8.HBYZ GIUQ(''@-A;8 +MC[J8L)R:2():>AZ](O_:%(?"I-#Z.9W^E7.ZKIK2PZ#;46OL]IKEX712BI#W +M@)R*VNL/\%A#ODMTD5X2X=[Q9OIN$/24<962BI&+AGY(\>'YDD*4PH^/ +MNKY.J%VOH_J Q=S4_D8AP82$F9YCBFM2EKY8T_#SDO8G]]FOOJ6ZFMLJ2(&U +MM\,&0<'6=]PC4E[2.YJWC(=2DKI4FJ/7[?:4TM,QMJ* +MHG&L7_'6,S8W[\&7M!Z']@"6MV!P>LT7(1FO@[.6I+R+BL97FH?T[>?_PQ.Z +MCX&/6B:ZI'+!P^KD]F7;XYY%V*AK6%I5@=%^^>)T)8&#\$S5E*V/.L.4^5C( +M5,+=R+!BQKV E?WM1Z 25TSJ$48UG\:;A*M[OZ:36 J1UAK'PD1WK:KJXO&3 +M5YZW6?Y/7O1J]XG1,:/3P#9PK )T_YDH'$QO7A_HFV_:8=MM#"#9"H\&:\FL\0!Y20FP)-KD!3'@' +M9QS&TPJ6.YUZOIAT4JS9T>7&.L"BOT>N0$D5ZT$Y@(,IS?W^R@/&0Q8&K$F> +M36U@6A" P96FL/KO@UY]5U9'DUF ?9)+:)1X7_%VDO2#5@=BZ^%P)B@M!9W +M\?/Y.F?0PHA0E%F^68(!\<[)6;V#GHZVI5^-I.H8_\9URI!0>G']G)Q^I-93 +M)]\%@*V)@\Z]]*^"@ 690?(M\"? UJN6DYV(3PVRDZ?QP=4N5J.(E[)]JBV3 +ME@-6"<0Y),?WVT]5G>VS [L[S]E;PE9:-$DRGHHY7\<)D[C8Z +M\4Z^1)\L4XB(GB:&T]KOX$\J*@# Q@V;AP"Z\$*?BLF&FL?S_>XR;L%_L%N% +M0%>6F-K>PO"YB9(KCZ-;JZ#B=/ P%H%R: +ME[:Z7\TBY?0R\,6#]I.;JB:65]M4HO.=TC_+K87TGY:3F >>ZL7 W-9R/\"& +MGDP\#-:!HV9P4MC]^DP Y32"G)!%B:^[2V!0>,GVP3WT_\J3._U>FY!#=HN@ +M6KMQ" 76P, 1SM*Y/JLA4E93>::0MI,1,=_&1E;"SLF4CHXA&GLD_P*!B8)0 +M?I6GN@/3_N^?@IJ$T2OW-/3F!UZ,FI1+'[\O.9H9TP %Q\I#XYR@G*6I +M6HT=.*:=PV+C-C 6\(J/<"H#WXD>XE4B#\[M"H8&E +MNJG ]1YN/ML:LY.4I%5: N#6V3!7D#0,E]&"@Z#RDQ8R]AM4"+25C@BZ66)T +M^DBVBS!0"<&6/3/EKQF'E*))LYNJ7Z>)PO)E[G?3"W+&E_I" +MKE6*CZS">+YV>_%ICII 3K96BVP"D]&L!(_& T 76K!$'\;ANJRZ\\U^,]6] +MQ9M:F([&_'"+EE1H7YO-2LG3^,/(@)"&K*Z@FEN_&Y_&7%W%]$7DQO;8O=!6 +MKOJ0G*K"[*"(K)P6.4^1*Z\BDH.4 +MDYHJ\L@)RP%&U-LXJ(?%E5P%DQ;T>DZ[YQ+&Q;O&PU@1AA^6E9A*\03:T)!0 +MHDL'E)*:S?O5_X:P@8/H+-W*[8>* +MO8F\F7JWD&NKL997O\#A]6S0^J,DE6L=XW'Q?0/\9._DE&QB1G6-] T +MQ@%=E*.QQ?F^$Y/^2I;>9_3"=VTE$\<;NQ=Q!#L&ZJH=?VEN/ +MTOY$\.X%:Q>3@K:XVZ7:@)F1E,?&]ZZ>\(V439X,DK)?^.MV4^// 0-L]-G_M2@IJ-"%J CKZ [MC#QLT/QQ_DY"MX"D +M)%%QP/3L+L CG;VBD9"PFITEP\K0,8F2K773NAMB\BT:,- ++%.TF[#W0%ML +M5 . YU/3GKP*VW2%JH*MMMTEN^UO]D\02H6KGKZ3A_>9O(73]O_ZY1-?I:E_ +MDXQ42TW9YO7^-Y>K2;2>+4FTE*K1^_:= +MTO6:ZIX$@IHZAY?RP,R?T0+,SY/O*@L(3XBU&W:_AUP&)J)RTV'0U^; )?22 +M%EU&4)99P-WS\:B$H[7;@WGS)]/1Y_07VZV*6;U45UY?*8Z:]PE%2:X*KR7OM-O0JU9U%LAN6@MR@DJP!^_'^4.-/?J&="D*=\HBJ1?''\#9Z +M\HZRFJ^'=_(ZPH*8<)5>AX\H +ME*2/@NTHZ>,C@P4'$DB7E0&[M@-#B^VGD0C#[J#@]8%0$(&[EZ"9@P%/HU&( +M5D&K@)*Z?0OO=EPJ'R].\D*"=$A$6FZ&.GLCS[,;V +M=M*O1:2+GIM25K%,6? 55/K.J8>ADQ^3!A/^H,R4)^_ZQ=..E9R5A4^^BT:@ +MFPK@U)A=;QX95L[_8EG9:>A8>)BYL(ZP44#Z:1])"*D8]A]/W5 +MFL2GKX">6W>BB(GH!9G2[L<6#YN1E+?$CDF&VOTGX/3&^EK=IWVX'_JJCXZ@ +MB?5\*VR@+NFF+F-K8+:M82(7[> M:Y*A3GUQ-_7VWVFEIZ B,&? +M;%Z_07SOUH_PH]'V$WR=$9 #K/OM9?K/XX>:D$J#JJRR!TIST<77PHOCHJ8O +MNE&5I+=, 3YYY\0Z$4*W_8VYA;MKH)03&,^,3<_B_$S&6HIOGE^-8;H+"?+M +ME_HV15">F5:#H%O\^7UZ.Z +MO#9$E%22B/+_VK2H&%H&DI6*P^23Y=6V18*5DE;VAG264O*'KT%^+1N':Q;I? +MNN:/U*BX7Q]Y6SQP3AZVCUO^'&Y20\)?UZFWEPL#Q^8@+N5(R_BB9@U/8 +M>9Q4?867FG[(WK6Z9CK'C%P!K;:@DL,YLE?9YZKZK:"+K-^=F:ZLFJ[1.9,N +M\,*XGQ8PDY.#&(ZPC-/ T1O4 -V:P?U**T9.FX ,TKFW_.93[Z:,.$*2/)D@ +M6J[##:Q4YMOQ@Z2]@$^3SU*( "TG/B7^IO)#BZZ0HIN.BYO4N\":U,[;XLK& +MUL/<0-^="H)>BY::2+>ZV7+P]:_P)8_)@)U4B;^Z\9><@UA_ +MB6RA:_<67Z.-GZ*_>(F=U8*4), O_/?P%6=.G,V7C V2J)7_4L#$R:E#\9^T +M?DS%CHBHJZ7XQ;05QKWN\*&J^QO6$Y*!EZF7K:-OPB]/G_SJU$=^SK> +MT[.2FM'[Y.V4^BN$$%&],J*J6Q5.TO0=EA.IAE*RG>TVE3__K=/P78G/O8D: +M]S!RFU%58S %G/*%59%8$\PPGN<^\7YEV_#+FL&]>^^<=B.EZ?XU=>X%CW"L +MET.G2"!?G_#DU1+0]MM-< YL2Q*-0)&0>T5O_\U/%<.&]]^,5W^!/6:.70$6 +MQ^_FTE#M?9DFD9"0JI>YE]WRSCB9C0_PLTO?P)SKHP@@ML_^SWMN^)6!!1GY"AJI'CO9U'(T#PK=S3 +MF4;7@KUAH(CJZL<0$,7!C;:YJIJO7;!Q1\7$-;_DQHJ:*/NJ.QS5H)G2]GFE +MY!#BF51_G#L83+TAM[;GR$C5U_=XCI!)GDD.BXULEXM(U/-W[Y;;4HA?BUI/ +MB9PRK+(-40V+Q#*O!)&\UB^?V*^"ADM.L(+2H4OQ +MT(P"HYU7@M.;\L*C.N_NVORP5ID$45F8P25*.WD(Z:4'A%@PSZ->_7UZ?XL_Y-M'B!DN4#PM94=DH,M_>87XGF +M+,?NU@5.?9:<\'U6J,!>BUG#QMQ?H90\E;$(@VP 5]*2967E]=&=ID7RF +M5$MH0,#$]'/'DI*X]H.#';)1O:"V\5 UDNZ]&Y>\KY>/JZP:&,*T?%G>/G)K!LX+(_ YUSPH'X\N(KMO!6)9M +MGO)*3E,BDC[&)&;/4=A6A10)@ZODV=CX_9(B'YN5JHKRPC5M[_Y0N(NCA5H) +M\C&CIJW7QO+"FI19K(^ASEVTAD+8H9;UT-'&F\:KJ]@0TM10K$6C]1 ?T6>R +M;%\*FX>/DT 1'K3NUL;E8Q"]B@V'[1LAVD$)"@ 6!-K(AY;0/)RX9:MLEY_- +M]-$P]B?;[YQY?H.62*BPI(^:P*I2*M$.2?. NYZ<@U9 FI&2H(_-Q^NN[O;^ +MRY!6K.18**7H:Z#Q+RC +MG_F<69ZY0 _#R//F]\6K$HF/D[J2CPA7@HA8T]76U\J[TBP?LI&H=8FO\.'D +M]^SZ)KM/C> ]<@%3EI(70.W>"N;"Q!22N)P4JX"3N*0^P-;U1L:N0ZB&F?#8 +MC[N6)NR<0LW]J8JHC8J:%^+5@M&C\S?O]'51H%I&FO"+F]D= +M$_6X0GY=D%F"6\-R-?+FQ8^=G*2M,(M""V/7FR+V +M-,6:_ZK^>6IMV_OUHK +MAK&2TT$/ZLCF5SF5=GF4N:C,ZI!T@N+DQS"^,E6_%?&UEC!B@')P3H+9#LCW +M6LC?&4"+3[=>J?J#FJ)LEI['\#7P;C;2EYRRD9HQEX+Q2O72?IB6G(Q0F8*C +M,A/P]/( J(.*O)^8B+MIH(+S[84<+_)X6U8(O\.CUE<@\OGW^LBUJ/:D6_'/ +MG[>3O<+V'>0^Q1*2(_*;N(:&G[ZA0/U]_?ONNQ*0+]Z:JXNML B@Z ?H!LN( +MJ:><@(SZ3IUSEI]!-^<;[O[#:9O=DIO6CU86@))?\?[KYNO(@&_5ARP1D7Q^ +MRISSD86:P/C&NB7D\_2)EM64>KFY@,+:X+PV4;BD=Y?;)_;S-OWPSZQ6RAF> +M5WFY0]HXRP.NN'JCF)TSE5JIQHR#X1 \]C!7-8U6:9J;HU):GTJ@QL%]XB5& +M_8R)K@_7L%.-US_NI]8VPI:6OHV]AXV3X%NZVJK4SXH"TKL5K]2)N)5'ME>= +MPO1%)'_^"KNRK4.)H$U2LF.?B6Y1%#9/;G?&)X-2N,_!6DEO,>0+QLS8R_\+^7-N]?;$*W2*$77##\1@J +M@8&;=Z>06^R"0^#1\;?_T^ 2I&P)2CBJ.J%,R/&VUO("BZ>D0WJA%);U9%+_ +MQ>;\QO.&E!BHETV.JR10\P/^#,%+43VILDF.HWN^BZQ6BQ?6]_;ZUO#K+ASS +MB;J-J9G!CIW)HAQ?(M_!0N&"GM\+GI)#5X.B-YCQOCE"_\8C68 6G8ZRB:CC +M52G0/AP+A;"0G/?EP>?6_/IS+!:)KL*7NAEF0#O SN=45""6G0ZALD#CEE/) +M%#3O]_'3DX!I@U&#OX1WG.S3P20ZP)*7H!.HK[.<%;C:GCSO_G/S ]91G\FH +M0;ML(%?-R@\:QHK0EUX1CXN+C:]F_XJ#%L7^P&Z(AU97]Y>>J)^F\+Y[2._D +M0]31 G$(N9/]&H!^F8A8L%.KP/XS.OXZY1J1^["0E*H+@O_STLQ0 Y$WEUJ> +M\JOLGN64X[Q<@;6>4*^+S');(-L'W*Y;^Y"0DU:"J::9XT(W\,+CP^<7J8BO +M@T:2D9H$P?COQNNFGY.#6AV2$HL:VI?V^A)'X3T:'$_M1HL.H8Y;%^0)_^?B +MXH./E$1>4X",V3;%=J+: +MDY>V5S9;K@Y3K,#0[])OUE.-O97MOU^)BL:$5_$*'N/' ,B4M%14G_8@CY:. +M4Q$V-7OE^EJYAY"UJ:>]=A*[LX.E!EC/S\@LSO&KJ)[SL?62B?*2AYK#*A7N +MTE?U?G >5:#1]I\%Z8'(#Y."T2 PO(#(T\"VKNB5Y+0L;/O]O-29YHJTI9+C%^5ZB#"/-#^R4:")9?ZJKX5HX!, +MH?37^BY/G19>FF2N()MMAL*IR$VHWO,<3I:L3;D&[U-F=K;A,A#OYF6A@Y+Y +MFP+R@7N*:80?AP)*S,\*5,J#JIN,B*FFDII3Q+!WPSKD]N7N\)J3E(MR@,.K +M$7\5V*YR7@Z:\-B6\^GJJDJ&"':%6;%SO%]L7_\,N&G:.>]XJ:,J16T*XV;).IO7\'T3)V^(:M?8[1YRL +MJR22D?0N=>M%EHN+Q +M4].#G@9@KYJ(G:P&EW'V-.+'^O/*EM%:T+Z?RJ'YDAOWB*ZG1) OTN6C2O&; +MC'^/ I!ACA+1X_?UTM.%4));FU:E3$/EUX-AD)#0^Q(3U@W',;\5L+O VI ? +MG+18F*DXA /'_,\+L+!3JX19J%OD$%W-,!&7]:L<&;V$@JGIE;K;X$F>EWK$ +MVP^>>8-3NHN=I5;EL";WYMK#UU^,; >]C4UCOG?HU"D9Q5LREIN?S R7N4TY +MI9,%,\3V5A &DH^,VX.5AIX&:;>0D0*LU\>-QL661T^-DT.=JH!*IEZ:PI#E +MEM>:P7^(0%U.2H*X[1G/\Y0+GBV7E192UZO\^O/N"YIQB\5&M+9;XM:M\1O/ +M'(6V,@2GDIZZH+>"QSO7+/J^/>"T>(JNCDB\ +MCZ5*X;6:Q_4>1T[_#QO"C_!6 +ME\4B-.X[RW#GIG1= X:MCHM/A^ 3];9PCJ7L0QB37Y33Z*USESO[^]B/4*Q( +MZ9N;CX7<\7$/VMT6P\F/W+F:2_I-K::"@,SD^?ODTH_HEJRS>O>'4[8%MZV@ +M_H1QR\_$CL&'GYV0J;6)3A& EYKG_O/D]NW%A$B(J5J1'*GKWZ<07)7[D1QS +M29+ ]G&6/I/+?(N3L0^=_)*4$-L(SP]D.)Q?A5>2FH%AI)<94;7FU@+(4H^@ +M5T.[#Z971@TPY^__SI*,H(M3@HCPA83 T_;2,!0!G)99KY:HJYUCAJ[#5I1\ +MK*4(OW2:1YFXC(:*5[_HU#WMM=;S0K95LUO5COI*;+9#$-@ X_]BRR>T4U>; +M1Q&0II821I.;)Z%%'"@%*^R6))6PYN_A"MY^@NVJ_08HFF&8R]GI]!1D^7P,#.;<\HYH] '8B/7LVK +M8$1;F9KL\C?Z3XJ2A7=U[6LR3C$]MY"PYH0>0F+?XRC +M3<#^;>[P9AJ)5 9-@IRE( !D,STJ>@(YJ75YHNKG[FM'S[/3P,@-) +MOME;5J1(G[N OXF% ONCRX_"CKR!E'V%J//GDY3!EY[-,A9G_:*3_>(DXLH +MAX#;:&SN,O<84)6 FM.I=HR5JL'B_/+D]5*VDIJYNPI&DHW17\=V=C[15W:( +MO#^&#HZXCDC-#?^O#=/27B_'RI6MPPI&NH.QEIJ* +M\,9" 5+,Q]K)F7@YFI9:+?R?H)^-I.(]%>[WCSV T;$Z,9:9!=SE$)B2$ECW +MD1J0P])O^[;$PKP*7H22H)NM0I/=*,-*_)"[FJF5]UH>IHY33>)6_;XK.X*C +MK;BS@OI&=8X TB&6VD^[GD&7^CV8SZ:M]-XNQ?Y@PVR6GZJ\VH]=H+79V\[* +MS0;2RK^RNHRL^Z6BK!X;K7*YQ].ZX^>!&)7O1KSG<;POB.\B()UL'2^6]+*V?*4D9.%4%37@<'F[,)O[\.. +M\(.;EG>"@SF7MJ7)V1 .B+*MFB%<@TR^B,/3D3!4TM!'Q[*=%\<(C[<&X./U +M^I;6DIV%@MJ2UH9(K:'P_ZEYX%EY_ +MU-SN>O+:])R$FP!QB8/1^87 A(A?FU2C?%+"PCCR$.6CNHBSK5H$KH/!WD'9 +M(P/R7"2&B38128FR]YK,\_E %^5)IX_#FKB-?I91@:+D%6[WU4_2;).L;Y^7 +MVK[-UM5VFL8;KJ2. 8FOKI,$L(K)5EP; L7REH_PK+V>1-*[EBG)$N\5R+E9:*T->.QAJ5L*5TRJO$O 6X4^0 +ME)2'7EZ;I8"!TJ * ]G?*\B>0M(- +M6MF1FM+ ?,?3[N*1EI"$AXF#@6P-FU/4\QF?O!&%CE5*6J2'@QDYV?_04-O) +M7Z 6N;C7E_4 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/tpg/94654-20170317-085441153.pts b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/tpg/94654-20170317-085441153.pts new file mode 100644 index 000000000..6760d5ec6 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/pts/tpg/94654-20170317-085441153.pts @@ -0,0 +1,289 @@ + +94654mynewt-Updated + + + L2CAP + 0
2
+ 1
3
+ 1
4
+ 1
5
+ 1
6
+ 2
40
+ 2
41
+ 2
42
+ 2
43
+ 2
45
+ 2
46
+ 2
47
+ 3
1
+ 3
12
+ 3
16
+
+ + GAP + 0
2
+ 0a
4
+ 10
1
+ 12
1
+ 13
1
+ 13
2
+ 14
1
+ 15
1
+ 16
1
+ 18
1
+ 18
2
+ 19
1
+ 19
2
+ 19
3
+ 20
1
+ 20
2
+ 20
3
+ 20
4
+ 20A
1
+ 20A
10
+ 20A
11
+ 20A
12
+ 20A
13
+ 20A
14
+ 20A
15
+ 20A
16
+ 20A
17
+ 20A
2
+ 20A
3
+ 20A
4
+ 20A
5
+ 20A
7
+ 20A
8
+ 20A
9
+ 21
1
+ 21
2
+ 21
3
+ 21
4
+ 21
5
+ 21
6
+ 21
7
+ 21
8
+ 21
9
+ 22
1
+ 22
2
+ 22
3
+ 22
4
+ 23
1
+ 23
2
+ 23
3
+ 23
4
+ 23
5
+ 24
1
+ 24
2
+ 24
3
+ 24
4
+ 25
1
+ 25
2
+ 25
3
+ 25
4
+ 25
7
+ 25
8
+ 25
9
+ 26
1
+ 26
2
+ 26
3
+ 26
4
+ 27
1
+ 27
2
+ 28
1
+ 28
2
+ 29
1
+ 29
2
+ 29
3
+ 29
4
+ 30
1
+ 30
2
+ 31
1
+ 31
2
+ 31
3
+ 31
4
+ 31
5
+ 31
6
+ 31
7
+ 31
8
+ 31
9
+ 32
1
+ 32
2
+ 32
3
+ 33
1
+ 33
2
+ 33
3
+ 33
4
+ 33
5
+ 33
6
+ 34
1
+ 34
2
+ 34
3
+ 35
1
+ 35
2
+ 35
3
+ 35
4
+ 35
5
+ 35
7
+ 35
8
+ 35
9
+ 37
1
+ 37
2
+ 37
3
+ 5
1
+ 5
2
+ 5
3
+ 5
4
+ 6
1
+ 7
1
+ 7
2
+ 8
1
+ 8
2
+ 8a
3
+ 9
1
+
+ + SUM ICS + + + PROD + + + GATT + 1
1
+ 1
2
+ 2
2
+ 3
1
+ 3
10
+ 3
11
+ 3
12
+ 3
14
+ 3
15
+ 3
16
+ 3
17
+ 3
18
+ 3
19
+ 3
2
+ 3
20
+ 3
21
+ 3
22
+ 3
23
+ 3
3
+ 3
4
+ 3
5
+ 3
6
+ 3
7
+ 3
8
+ 3
9
+ 4
1
+ 4
10
+ 4
11
+ 4
12
+ 4
14
+ 4
15
+ 4
16
+ 4
17
+ 4
18
+ 4
19
+ 4
2
+ 4
20
+ 4
21
+ 4
22
+ 4
23
+ 4
3
+ 4
4
+ 4
5
+ 4
6
+ 4
7
+ 4
8
+ 4
9
+ 7
2
+ 7
3
+ 7
4
+
+ + ATT + 1
1
+ 1
2
+ 2
2
+ 3
1
+ 3
10
+ 3
11
+ 3
12
+ 3
13
+ 3
14
+ 3
15
+ 3
16
+ 3
17
+ 3
18
+ 3
19
+ 3
2
+ 3
20
+ 3
22
+ 3
23
+ 3
24
+ 3
25
+ 3
26
+ 3
27
+ 3
28
+ 3
29
+ 3
3
+ 3
4
+ 3
5
+ 3
6
+ 3
7
+ 3
8
+ 3
9
+ 4
1
+ 4
10
+ 4
11
+ 4
12
+ 4
13
+ 4
14
+ 4
15
+ 4
16
+ 4
17
+ 4
18
+ 4
19
+ 4
2
+ 4
20
+ 4
22
+ 4
23
+ 4
24
+ 4
25
+ 4
26
+ 4
27
+ 4
28
+ 4
29
+ 4
3
+ 4
4
+ 4
5
+ 4
6
+ 4
7
+ 4
8
+ 4
9
+ 5
2
+ 5
3
+ 5
4
+
+ + SM + 1
1
+ 1
2
+ 2
1
+ 2
2
+ 2
3
+ 2
5
+ 3
1
+ 4
1
+ 4
2
+ 5
1
+ 5
2
+ 5
3
+ 5
4
+ 7
1
+ 7
2
+ 7
3
+
+
+
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/services/ans/ble_svc_ans.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ans/include/services/ans/ble_svc_ans.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/services/ans/ble_svc_ans.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ans/include/services/ans/ble_svc_ans.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ans/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ans/pkg.yml new file mode 100644 index 000000000..691e566e1 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ans/pkg.yml @@ -0,0 +1,34 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: nimble/host/services/ans +pkg.description: Alert Notification Service Server. +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - ble + - bluetooth + - ans + - nimble + +pkg.deps: + - nimble/host + +pkg.init: + ble_svc_ans_init: 'MYNEWT_VAL(BLE_SVC_ANS_SYSINIT_STAGE)' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/ans/src/ble_svc_ans.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ans/src/ble_svc_ans.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/ans/src/ble_svc_ans.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ans/src/ble_svc_ans.c index 5b64f18c4..2fc50c4be 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/ans/src/ble_svc_ans.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ans/src/ble_svc_ans.c @@ -20,11 +20,11 @@ #include #include -#include "sysinit/sysinit.h" -#include "syscfg/syscfg.h" -#include "host/ble_hs.h" -#include "host/ble_gap.h" -#include "services/ans/ble_svc_ans.h" +#include "nimble/porting/nimble/include/sysinit/sysinit.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/nimble/host/include/host/ble_hs.h" +#include "nimble/nimble/host/include/host/ble_gap.h" +#include "../include/services/ans/ble_svc_ans.h" /* Max length of new alert info string */ #define BLE_SVC_ANS_INFO_STR_MAX_LEN 18 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ans/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ans/syscfg.yml new file mode 100644 index 000000000..74de8d963 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ans/syscfg.yml @@ -0,0 +1,30 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +syscfg.defs: + BLE_SVC_ANS_NEW_ALERT_CAT: + description: "Initial supported new alert category bitmask." + value: 0 + + BLE_SVC_ANS_UNR_ALERT_CAT: + description: "Initial supported unread alert category bitmask." + value: 0 + + BLE_SVC_ANS_SYSINIT_STAGE: + description: > + Sysinit stage for the alert notification service. + value: 303 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/services/bas/ble_svc_bas.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/include/services/bas/ble_svc_bas.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/services/bas/ble_svc_bas.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/include/services/bas/ble_svc_bas.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/pkg.yml new file mode 100644 index 000000000..afdc69421 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/pkg.yml @@ -0,0 +1,34 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: nimble/host/services/bas +pkg.description: Battery Service +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - ble + - bluetooth + - bas + - nimble + +pkg.deps: + - nimble/host + +pkg.init: + ble_svc_bas_init: 'MYNEWT_VAL(BLE_SVC_BAS_SYSINIT_STAGE)' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/bas/src/ble_svc_bas.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/src/ble_svc_bas.c similarity index 92% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/bas/src/ble_svc_bas.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/src/ble_svc_bas.c index 631519cf9..317b11627 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/bas/src/ble_svc_bas.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/src/ble_svc_bas.c @@ -20,11 +20,11 @@ #include #include -#include "sysinit/sysinit.h" -#include "syscfg/syscfg.h" -#include "host/ble_hs.h" -#include "host/ble_gap.h" -#include "services/bas/ble_svc_bas.h" +#include "nimble/porting/nimble/include/sysinit/sysinit.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/nimble/host/include/host/ble_hs.h" +#include "nimble/nimble/host/include/host/ble_gap.h" +#include "../include/services/bas/ble_svc_bas.h" /* Characteristic value handles */ #if MYNEWT_VAL(BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE) > 0 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/syscfg.yml new file mode 100644 index 000000000..279930f14 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/syscfg.yml @@ -0,0 +1,34 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +syscfg.defs: + BLE_SVC_BAS_BATTERY_LEVEL_READ_PERM: + description: > + Defines permissions for reading "Battery Level" characteristics. Can + be zero to allow read without extra permissions or combination of: + BLE_GATT_CHR_F_READ_ENC + BLE_GATT_CHR_F_READ_AUTHEN + BLE_GATT_CHR_F_READ_AUTHOR + value: 0 + BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE: + description: > + Set to 1 to support notification or 0 to disable it. + value: 1 + BLE_SVC_BAS_SYSINIT_STAGE: + description: > + Sysinit stage for the battery level service. + value: 303 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/include/services/dis/ble_svc_dis.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/include/services/dis/ble_svc_dis.h new file mode 100644 index 000000000..d095e959a --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/include/services/dis/ble_svc_dis.h @@ -0,0 +1,113 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_SVC_DIS_ +#define H_BLE_SVC_DIS_ + +/** + * Example: + * + * char firmware_revision[20] = '?.?.?'; + * struct image_version iv; + * if (!imgr_my_version(&iv)) { + * snprintf(firmware_revision, sizeof(firmware_revision), + * "%u.%u.%u", iv.iv_major, iv.iv_minor, iv.iv_revision); + * } + * ble_svc_dis_manufacturer_name_set("MyNewt"); + * ble_svc_dis_firmware_revision_set(firmware_revision); + * + */ + +#define BLE_SVC_DIS_UUID16 0x180A +#define BLE_SVC_DIS_CHR_UUID16_SYSTEM_ID 0x2A23 +#define BLE_SVC_DIS_CHR_UUID16_MODEL_NUMBER 0x2A24 +#define BLE_SVC_DIS_CHR_UUID16_SERIAL_NUMBER 0x2A25 +#define BLE_SVC_DIS_CHR_UUID16_FIRMWARE_REVISION 0x2A26 +#define BLE_SVC_DIS_CHR_UUID16_HARDWARE_REVISION 0x2A27 +#define BLE_SVC_DIS_CHR_UUID16_SOFTWARE_REVISION 0x2A28 +#define BLE_SVC_DIS_CHR_UUID16_MANUFACTURER_NAME 0x2A29 + +/** + * Structure holding data for the main characteristics + */ +struct ble_svc_dis_data { + /** + * Model number. + * Represent the model number that is assigned by the device vendor. + */ + const char *model_number; + /** + * Serial number. + * Represent the serial number for a particular instance of the device. + */ + const char *serial_number; + /** + * Firmware revision. + * Represent the firmware revision for the firmware within the device. + */ + const char *firmware_revision; + /** + * Hardware revision. + * Represent the hardware revision for the hardware within the device. + */ + const char *hardware_revision; + /** + * Software revision. + * Represent the software revision for the software within the device. + */ + const char *software_revision; + /** + * Manufacturer name. + * Represent the name of the manufacturer of the device. + */ + const char *manufacturer_name; + /** + * System ID. + * Represent the System Id of the device. + */ + const char *system_id; +}; + +/** + * Variable holding data for the main characteristics. + */ +extern struct ble_svc_dis_data ble_svc_dis_data; + +/** + * Service initialisation. + * Automatically called during package initialisation. + */ +void ble_svc_dis_init(void); + +const char *ble_svc_dis_model_number(void); +int ble_svc_dis_model_number_set(const char *value); +const char *ble_svc_dis_serial_number(void); +int ble_svc_dis_serial_number_set(const char *value); +const char *ble_svc_dis_firmware_revision(void); +int ble_svc_dis_firmware_revision_set(const char *value); +const char *ble_svc_dis_hardware_revision(void); +int ble_svc_dis_hardware_revision_set(const char *value); +const char *ble_svc_dis_software_revision(void); +int ble_svc_dis_software_revision_set(const char *value); +const char *ble_svc_dis_manufacturer_name(void); +int ble_svc_dis_manufacturer_name_set(const char *value); +const char *ble_svc_dis_system_id(void); +int ble_svc_dis_system_id_set(const char *value); + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/pkg.yml new file mode 100644 index 000000000..b914ca90a --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/pkg.yml @@ -0,0 +1,34 @@ + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: nimble/host/services/dis +pkg.description: Device Information Service Implementation. +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - ble + - bluetooth + - dis + - nimble + +pkg.deps: + - nimble/host + +pkg.init: + ble_svc_dis_init: 'MYNEWT_VAL(BLE_SVC_DIS_SYSINIT_STAGE)' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/src/ble_svc_dis.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/src/ble_svc_dis.c new file mode 100644 index 000000000..55c6f1d56 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/src/ble_svc_dis.c @@ -0,0 +1,331 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include "nimble/porting/nimble/include/sysinit/sysinit.h" +#include "nimble/nimble/host/include/host/ble_hs.h" +#include "../include/services/dis/ble_svc_dis.h" + +/* Device information */ +struct ble_svc_dis_data ble_svc_dis_data = { + .model_number = MYNEWT_VAL(BLE_SVC_DIS_MODEL_NUMBER_DEFAULT), + .serial_number = MYNEWT_VAL(BLE_SVC_DIS_SERIAL_NUMBER_DEFAULT), + .firmware_revision = MYNEWT_VAL(BLE_SVC_DIS_FIRMWARE_REVISION_DEFAULT), + .hardware_revision = MYNEWT_VAL(BLE_SVC_DIS_HARDWARE_REVISION_DEFAULT), + .software_revision = MYNEWT_VAL(BLE_SVC_DIS_SOFTWARE_REVISION_DEFAULT), + .manufacturer_name = MYNEWT_VAL(BLE_SVC_DIS_MANUFACTURER_NAME_DEFAULT), + .system_id = MYNEWT_VAL(BLE_SVC_DIS_SYSTEM_ID_DEFAULT), +}; + +/* Access function */ +#if (MYNEWT_VAL(BLE_SVC_DIS_MODEL_NUMBER_READ_PERM) >= 0) || \ + (MYNEWT_VAL(BLE_SVC_DIS_SERIAL_NUMBER_READ_PERM) >= 0) || \ + (MYNEWT_VAL(BLE_SVC_DIS_HARDWARE_REVISION_READ_PERM) >= 0) || \ + (MYNEWT_VAL(BLE_SVC_DIS_FIRMWARE_REVISION_READ_PERM) >= 0) || \ + (MYNEWT_VAL(BLE_SVC_DIS_SOFTWARE_REVISION_READ_PERM) >= 0) || \ + (MYNEWT_VAL(BLE_SVC_DIS_MANUFACTURER_NAME_READ_PERM) >= 0) || \ + (MYNEWT_VAL(BLE_SVC_DIS_SYSTEM_ID_READ_PERM) >= 0) +static int +ble_svc_dis_access(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg); +#endif + +static const struct ble_gatt_svc_def ble_svc_dis_defs[] = { + { /*** Service: Device Information Service (DIS). */ + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid = BLE_UUID16_DECLARE(BLE_SVC_DIS_UUID16), + .characteristics = (struct ble_gatt_chr_def[]) { { +#if (MYNEWT_VAL(BLE_SVC_DIS_MODEL_NUMBER_READ_PERM) >= 0) + /*** Characteristic: Model Number String */ + .uuid = BLE_UUID16_DECLARE(BLE_SVC_DIS_CHR_UUID16_MODEL_NUMBER), + .access_cb = ble_svc_dis_access, + .flags = BLE_GATT_CHR_F_READ | + MYNEWT_VAL(BLE_SVC_DIS_MODEL_NUMBER_READ_PERM), + }, { +#endif +#if (MYNEWT_VAL(BLE_SVC_DIS_SERIAL_NUMBER_READ_PERM) >= 0) + /*** Characteristic: Serial Number String */ + .uuid = BLE_UUID16_DECLARE(BLE_SVC_DIS_CHR_UUID16_SERIAL_NUMBER), + .access_cb = ble_svc_dis_access, + .flags = BLE_GATT_CHR_F_READ | + MYNEWT_VAL(BLE_SVC_DIS_SERIAL_NUMBER_READ_PERM), + }, { +#endif +#if (MYNEWT_VAL(BLE_SVC_DIS_HARDWARE_REVISION_READ_PERM) >= 0) + /*** Characteristic: Hardware Revision String */ + .uuid = BLE_UUID16_DECLARE(BLE_SVC_DIS_CHR_UUID16_HARDWARE_REVISION), + .access_cb = ble_svc_dis_access, + .flags = BLE_GATT_CHR_F_READ | + MYNEWT_VAL(BLE_SVC_DIS_HARDWARE_REVISION_READ_PERM), + }, { +#endif +#if (MYNEWT_VAL(BLE_SVC_DIS_FIRMWARE_REVISION_READ_PERM) >= 0) + /*** Characteristic: Firmware Revision String */ + .uuid = BLE_UUID16_DECLARE(BLE_SVC_DIS_CHR_UUID16_FIRMWARE_REVISION), + .access_cb = ble_svc_dis_access, + .flags = BLE_GATT_CHR_F_READ | + MYNEWT_VAL(BLE_SVC_DIS_FIRMWARE_REVISION_READ_PERM), + }, { +#endif +#if (MYNEWT_VAL(BLE_SVC_DIS_SOFTWARE_REVISION_READ_PERM) >= 0) + /*** Characteristic: Software Revision String */ + .uuid = BLE_UUID16_DECLARE(BLE_SVC_DIS_CHR_UUID16_SOFTWARE_REVISION), + .access_cb = ble_svc_dis_access, + .flags = BLE_GATT_CHR_F_READ | + MYNEWT_VAL(BLE_SVC_DIS_SOFTWARE_REVISION_READ_PERM), + }, { +#endif +#if (MYNEWT_VAL(BLE_SVC_DIS_MANUFACTURER_NAME_READ_PERM) >= 0) + /*** Characteristic: Manufacturer Name */ + .uuid = BLE_UUID16_DECLARE(BLE_SVC_DIS_CHR_UUID16_MANUFACTURER_NAME), + .access_cb = ble_svc_dis_access, + .flags = BLE_GATT_CHR_F_READ | + MYNEWT_VAL(BLE_SVC_DIS_MANUFACTURER_NAME_READ_PERM), + }, { +#endif +#if (MYNEWT_VAL(BLE_SVC_DIS_SYSTEM_ID_READ_PERM) >= 0) + /*** Characteristic: System Id */ + .uuid = BLE_UUID16_DECLARE(BLE_SVC_DIS_CHR_UUID16_SYSTEM_ID), + .access_cb = ble_svc_dis_access, + .flags = BLE_GATT_CHR_F_READ | + MYNEWT_VAL(BLE_SVC_DIS_SYSTEM_ID_READ_PERM), + }, { +#endif + + 0, /* No more characteristics in this service */ + }, } + }, + + { + 0, /* No more services. */ + }, +}; + +/** + * Simple read access callback for the device information service + * characteristic. + */ +#if (MYNEWT_VAL(BLE_SVC_DIS_MODEL_NUMBER_READ_PERM) >= 0) || \ + (MYNEWT_VAL(BLE_SVC_DIS_SERIAL_NUMBER_READ_PERM) >= 0) || \ + (MYNEWT_VAL(BLE_SVC_DIS_HARDWARE_REVISION_READ_PERM) >= 0) || \ + (MYNEWT_VAL(BLE_SVC_DIS_FIRMWARE_REVISION_READ_PERM) >= 0) || \ + (MYNEWT_VAL(BLE_SVC_DIS_SOFTWARE_REVISION_READ_PERM) >= 0) || \ + (MYNEWT_VAL(BLE_SVC_DIS_MANUFACTURER_NAME_READ_PERM) >= 0) || \ + (MYNEWT_VAL(BLE_SVC_DIS_SYSTEM_ID_READ_PERM) >= 0) +static int +ble_svc_dis_access(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg) +{ + uint16_t uuid = ble_uuid_u16(ctxt->chr->uuid); + const char *info = NULL; + + switch(uuid) { +#if (MYNEWT_VAL(BLE_SVC_DIS_MODEL_NUMBER_READ_PERM) >= 0) + case BLE_SVC_DIS_CHR_UUID16_MODEL_NUMBER: + info = ble_svc_dis_data.model_number; +#ifdef MYNEWT_VAL_BLE_SVC_DIS_MODEL_NUMBER_NAME_DEFAULT + if (info == NULL) { + info = MYNEWT_VAL(BLE_SVC_DIS_MODEL_NUMBER_DEFAULT); + } +#endif + break; +#endif +#if (MYNEWT_VAL(BLE_SVC_DIS_SERIAL_NUMBER_READ_PERM) >= 0) + case BLE_SVC_DIS_CHR_UUID16_SERIAL_NUMBER: + info = ble_svc_dis_data.serial_number; +#ifdef MYNEWT_VAL_BLE_SVC_DIS_SERIAL_NUMBER_DEFAULT + if (info == NULL) { + info = MYNEWT_VAL(BLE_SVC_DIS_SERIAL_NUMBER_DEFAULT); + } +#endif + break; +#endif +#if (MYNEWT_VAL(BLE_SVC_DIS_FIRMWARE_REVISION_READ_PERM) >= 0) + case BLE_SVC_DIS_CHR_UUID16_FIRMWARE_REVISION: + info = ble_svc_dis_data.firmware_revision; +#ifdef MYNEWT_VAL_BLE_SVC_DIS_FIRMWARE_REVISION_DEFAULT + if (info == NULL) { + info = MYNEWT_VAL(BLE_SVC_DIS_FIRMWARE_REVISION_DEFAULT); + } +#endif + break; +#endif +#if (MYNEWT_VAL(BLE_SVC_DIS_HARDWARE_REVISION_READ_PERM) >= 0) + case BLE_SVC_DIS_CHR_UUID16_HARDWARE_REVISION: + info = ble_svc_dis_data.hardware_revision; +#ifdef MYNEWT_VAL_BLE_SVC_DIS_HARDWARE_REVISION_DEFAULT + if (info == NULL) { + info = MYNEWT_VAL(BLE_SVC_DIS_HARDWARE_REVISION_DEFAULT); + } +#endif + break; +#endif +#if (MYNEWT_VAL(BLE_SVC_DIS_SOFTWARE_REVISION_READ_PERM) >= 0) + case BLE_SVC_DIS_CHR_UUID16_SOFTWARE_REVISION: + info = ble_svc_dis_data.software_revision; +#ifdef MYNEWT_VAL_BLE_SVC_DIS_SOFTWARE_REVISION_DEFAULT + if (info == NULL) { + info = MYNEWT_VAL(BLE_SVC_DIS_SOFTWARE_REVISION_DEFAULT); + } +#endif + break; +#endif +#if (MYNEWT_VAL(BLE_SVC_DIS_MANUFACTURER_NAME_READ_PERM) >= 0) + case BLE_SVC_DIS_CHR_UUID16_MANUFACTURER_NAME: + info = ble_svc_dis_data.manufacturer_name; +#ifdef MYNEWT_VAL_BLE_SVC_DIS_MANUFACTURER_NAME_DEFAULT + if (info == NULL) { + info = MYNEWT_VAL(BLE_SVC_DIS_MANUFACTURER_NAME_DEFAULT); + } +#endif + break; +#endif +#if (MYNEWT_VAL(BLE_SVC_DIS_SYSTEM_ID_READ_PERM) >= 0) + case BLE_SVC_DIS_CHR_UUID16_SYSTEM_ID: + info = ble_svc_dis_data.system_id; +#ifdef MYNEWT_VAL_BLE_SVC_DIS_SYSTEM_ID_DEFAULT + if (info == NULL) { + info = MYNEWT_VAL(BLE_SVC_DIS_SYSTEM_ID_DEFAULT); + } +#endif + break; +#endif + default: + assert(0); + return BLE_ATT_ERR_UNLIKELY; + } + + if (info != NULL) { + int rc = os_mbuf_append(ctxt->om, info, strlen(info)); + return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + } + + return 0; +} +#endif + +const char * +ble_svc_dis_model_number(void) +{ + return ble_svc_dis_data.model_number; +} + +int +ble_svc_dis_model_number_set(const char *value) +{ + ble_svc_dis_data.model_number = value; + return 0; +} + +const char * +ble_svc_dis_serial_number(void) +{ + return ble_svc_dis_data.serial_number; +} + +int +ble_svc_dis_serial_number_set(const char *value) +{ + ble_svc_dis_data.serial_number = value; + return 0; +} + +const char * +ble_svc_dis_firmware_revision(void) +{ + return ble_svc_dis_data.firmware_revision; +} + +int +ble_svc_dis_firmware_revision_set(const char *value) +{ + ble_svc_dis_data.firmware_revision = value; + return 0; +} + +const char * +ble_svc_dis_hardware_revision(void) +{ + return ble_svc_dis_data.hardware_revision; +} + +int +ble_svc_dis_hardware_revision_set(const char *value) +{ + ble_svc_dis_data.hardware_revision = value; + return 0; +} + +const char * +ble_svc_dis_software_revision(void) +{ + return ble_svc_dis_data.software_revision; +} + +int +ble_svc_dis_software_revision_set(const char *value) +{ + ble_svc_dis_data.software_revision = value; + return 0; +} + +const char * +ble_svc_dis_manufacturer_name(void) +{ + return ble_svc_dis_data.manufacturer_name; +} + +int +ble_svc_dis_manufacturer_name_set(const char *value) +{ + ble_svc_dis_data.manufacturer_name = value; + return 0; +} + +const char * +ble_svc_dis_system_id(void) +{ + return ble_svc_dis_data.system_id; +} + +int +ble_svc_dis_system_id_set(const char *value) +{ + ble_svc_dis_data.system_id = value; + return 0; +} + +/** + * Initialize the DIS package. + */ +void +ble_svc_dis_init(void) +{ + int rc; + + /* Ensure this function only gets called by sysinit. */ + SYSINIT_ASSERT_ACTIVE(); + + rc = ble_gatts_count_cfg(ble_svc_dis_defs); + SYSINIT_PANIC_ASSERT(rc == 0); + + rc = ble_gatts_add_svcs(ble_svc_dis_defs); + SYSINIT_PANIC_ASSERT(rc == 0); +} diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/syscfg.yml new file mode 100644 index 000000000..b306d3bb5 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/dis/syscfg.yml @@ -0,0 +1,109 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +syscfg.defs: + BLE_SVC_DIS_DEFAULT_READ_PERM: + description: > + Defines default permissions for reading characteristics. Can be + zero to allow read without extra permissions or combination of: + BLE_GATT_CHR_F_READ_ENC + BLE_GATT_CHR_F_READ_AUTHEN + BLE_GATT_CHR_F_READ_AUTHOR + Set to '-1' to remove this characteristic. + value: -1 + BLE_SVC_DIS_MODEL_NUMBER_READ_PERM: + description: > + Defines permissions for reading "Model Number" characteristics. + Can be set to BLE_SVC_DIS_DEFAULT_READ_PERM or use any of the + possible values defined for that setting. + value: 0 + BLE_SVC_DIS_MODEL_NUMBER_DEFAULT: + description: > + Defines a default value for "Model number" if not set with + 'ble_svc_dis_model_number_set'. + value: '"Apache Mynewt NimBLE"' + BLE_SVC_DIS_SERIAL_NUMBER_READ_PERM: + description: > + Defines permissions for reading "Serial Number" characteristics. + Can be set to BLE_SVC_DIS_DEFAULT_READ_PERM or use any of the + possible values defined for that setting. + value: MYNEWT_VAL(BLE_SVC_DIS_DEFAULT_READ_PERM) + BLE_SVC_DIS_SERIAL_NUMBER_DEFAULT: + description: > + Defines a default value for "Serial number" if not set with + 'ble_svc_dis_serial_number_set'. + value: NULL + BLE_SVC_DIS_HARDWARE_REVISION_READ_PERM: + description: > + Defines permissions for reading "Hardware Revision" characteristics. + Can be set to BLE_SVC_DIS_DEFAULT_READ_PERM or use any of the + possible values defined for that setting. + value: MYNEWT_VAL(BLE_SVC_DIS_DEFAULT_READ_PERM) + BLE_SVC_DIS_HARDWARE_REVISION_DEFAULT: + description: > + Defines a default value for "Hardware revision" if not set with + 'ble_svc_dis_hardware_revision_set'. + value: NULL + BLE_SVC_DIS_FIRMWARE_REVISION_READ_PERM: + description: > + Defines permissions for reading "Firmware Revision" characteristics. + Can be set to BLE_SVC_DIS_DEFAULT_READ_PERM or use any of the + possible values defined for that setting. + value: MYNEWT_VAL(BLE_SVC_DIS_DEFAULT_READ_PERM) + BLE_SVC_DIS_FIRMWARE_REVISION_DEFAULT: + description: > + Defines a default value for "Software revision" if not set with + 'ble_svc_dis_firmware_revision_set'. + value: NULL + BLE_SVC_DIS_SOFTWARE_REVISION_READ_PERM: + description: > + Defines permissions for reading "Software Revision" characteristics. + Can be set to BLE_SVC_DIS_DEFAULT_READ_PERM or use any of the + possible values defined for that setting. + value: MYNEWT_VAL(BLE_SVC_DIS_DEFAULT_READ_PERM) + BLE_SVC_DIS_SOFTWARE_REVISION_DEFAULT: + description: > + Defines a default value for "Software revision" if not set with + 'ble_svc_dis_software_revision_set'. + value: NULL + BLE_SVC_DIS_MANUFACTURER_NAME_READ_PERM: + description: > + Defines permissions for reading "Manufacturer name" characteristics. + Can be set to BLE_SVC_DIS_DEFAULT_READ_PERM or use any of the + possible values defined for that setting. + value: MYNEWT_VAL(BLE_SVC_DIS_DEFAULT_READ_PERM) + BLE_SVC_DIS_MANUFACTURER_NAME_DEFAULT: + description: > + Defines a default value for "Manufacturer name" if not set with + 'ble_svc_dis_manufacturer_name_set'. + value: NULL + BLE_SVC_DIS_SYSTEM_ID_READ_PERM: + description: > + Defines permissions for reading "System ID" characteristics. + Can be set to BLE_SVC_DIS_DEFAULT_READ_PERM or use any of the + possible values defined for that setting. + value: MYNEWT_VAL(BLE_SVC_DIS_DEFAULT_READ_PERM) + BLE_SVC_DIS_SYSTEM_ID_DEFAULT: + description: > + Defines a default value for "System ID" if not set with + 'ble_svc_dis_manufacturer_name_set'. + value: NULL + BLE_SVC_DIS_SYSINIT_STAGE: + description: > + Sysinit stage for the device information BLE service. + value: 303 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/services/gap/ble_svc_gap.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/services/gap/ble_svc_gap.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/pkg.yml new file mode 100644 index 000000000..a2ef756e3 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/pkg.yml @@ -0,0 +1,34 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: nimble/host/services/gap +pkg.description: Implements the GAP Service. +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - ble + - bluetooth + - nimble + - gap + +pkg.deps: + - nimble/host + +pkg.init: + ble_svc_gap_init: 'MYNEWT_VAL(BLE_SVC_GAP_SYSINIT_STAGE)' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/gap/src/ble_svc_gap.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/src/ble_svc_gap.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/gap/src/ble_svc_gap.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/src/ble_svc_gap.c index e79b2b872..f1cf2d9ba 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/gap/src/ble_svc_gap.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/src/ble_svc_gap.c @@ -20,10 +20,10 @@ #include #include -#include "sysinit/sysinit.h" -#include "host/ble_hs.h" -#include "services/gap/ble_svc_gap.h" -#include "os/endian.h" +#include "nimble/porting/nimble/include/sysinit/sysinit.h" +#include "nimble/nimble/host/include/host/ble_hs.h" +#include "../include/services/gap/ble_svc_gap.h" +#include "nimble/porting/nimble/include/os/endian.h" #define PPCP_ENABLED \ MYNEWT_VAL(BLE_ROLE_PERIPHERAL) && \ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/syscfg.yml new file mode 100644 index 000000000..ad6aa7ef3 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/syscfg.yml @@ -0,0 +1,83 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +syscfg.defs: + BLE_SVC_GAP_DEVICE_NAME: + description: > + Default value for "Device Name" characteristics, unless overwritten + by application. + value: '"nimble"' + BLE_SVC_GAP_DEVICE_NAME_WRITE_PERM: + description: > + Defines permissions for writing "Device Name" characteristics. Can + be zero to allow write without extra permissions or combination of: + BLE_GATT_CHR_F_WRITE_ENC + BLE_GATT_CHR_F_WRITE_AUTHEN + BLE_GATT_CHR_F_WRITE_AUTHOR + Set to '-1' to make characteristic read only. + value: -1 + BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH: + description: Maximum length for "Device Name" characteristics + value: 31 + BLE_SVC_GAP_APPEARANCE: + description: 'Device appearance' + value: 0 + BLE_SVC_GAP_APPEARANCE_WRITE_PERM: + description: > + Defines permissions for writing "Appearance" characteristics. Can + be zero to allow write without extra permissions or combination of: + BLE_GATT_CHR_F_WRITE_ENC + BLE_GATT_CHR_F_WRITE_AUTHEN + BLE_GATT_CHR_F_WRITE_AUTHOR + Set to '-1' to make characteristic read only. + value: -1 + + # Setting all values for PPCP to '0' will disable characteristic! + BLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL: + description: > + Value of "minimum connection interval" of PPCP characteristic as + defined by Core specification 5.0, Vol 3, Part C, section 12.3. + value: 0 + BLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL: + description: > + Value of "maximum connection interval" of PPCP characteristic as + defined by Core specification 5.0, Vol 3, Part C, section 12.3. + value: 0 + BLE_SVC_GAP_PPCP_SLAVE_LATENCY: + description: > + Value of "slave latency" of PPCP characteristic as defined by Core + specification 5.0, Vol 3, Part C, section 12.3. + value: 0 + BLE_SVC_GAP_PPCP_SUPERVISION_TMO: + description: > + Value of "connection supervision timeout multiplier" of PPCP + characteristic as defined by Core specification 5.0, Vol 3, Part C, + section 12.3. + value: 0 + + BLE_SVC_GAP_CENTRAL_ADDRESS_RESOLUTION: + description: > + Value of "Central Address Resolution" characteristics, as defined + by Core specification 5.0, Vol 3, Part C, section 12. + Set to '-1' to disable. + value: -1 + + BLE_SVC_GAP_SYSINIT_STAGE: + description: > + Sysinit stage for the GAP BLE service. + value: 301 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/services/gatt/ble_svc_gatt.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/services/gatt/ble_svc_gatt.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gatt/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gatt/pkg.yml new file mode 100644 index 000000000..e3704bc18 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gatt/pkg.yml @@ -0,0 +1,34 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: nimble/host/services/gatt +pkg.description: Implements the GATT service. +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - ble + - bluetooth + - nimble + - gatt + +pkg.deps: + - nimble/host + +pkg.init: + ble_svc_gatt_init: 'MYNEWT_VAL(BLE_SVC_GATT_SYSINIT_STAGE)' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/gatt/src/ble_svc_gatt.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gatt/src/ble_svc_gatt.c similarity index 95% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/gatt/src/ble_svc_gatt.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gatt/src/ble_svc_gatt.c index 78b4a0683..eef3c49ba 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/gatt/src/ble_svc_gatt.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gatt/src/ble_svc_gatt.c @@ -19,9 +19,9 @@ #include -#include "sysinit/sysinit.h" -#include "host/ble_hs.h" -#include "services/gatt/ble_svc_gatt.h" +#include "nimble/porting/nimble/include/sysinit/sysinit.h" +#include "nimble/nimble/host/include/host/ble_hs.h" +#include "../include/services/gatt/ble_svc_gatt.h" static uint16_t ble_svc_gatt_changed_val_handle; static uint16_t ble_svc_gatt_start_handle; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gatt/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gatt/syscfg.yml new file mode 100644 index 000000000..6ba1b333e --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gatt/syscfg.yml @@ -0,0 +1,24 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +syscfg.defs: + BLE_SVC_GATT_SYSINIT_STAGE: + description: > + Sysinit stage for the GATT BLE service + value: 302 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/services/ias/ble_svc_ias.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ias/include/services/ias/ble_svc_ias.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/services/ias/ble_svc_ias.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ias/include/services/ias/ble_svc_ias.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ias/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ias/pkg.yml new file mode 100644 index 000000000..3b0ca0745 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ias/pkg.yml @@ -0,0 +1,34 @@ + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: nimble/host/services/ias +pkg.description: Immediate Alert Service Implementation. +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - ble + - bluetooth + - ias + - nimble + +pkg.deps: + - nimble/host + +pkg.init: + ble_svc_ias_init: 'MYNEWT_VAL(BLE_SVC_IAS_SYSINIT_STAGE)' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/ias/src/ble_svc_ias.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ias/src/ble_svc_ias.c similarity index 96% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/ias/src/ble_svc_ias.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ias/src/ble_svc_ias.c index 9f5da1485..98be867f1 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/ias/src/ble_svc_ias.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ias/src/ble_svc_ias.c @@ -19,9 +19,9 @@ #include #include -#include "sysinit/sysinit.h" -#include "host/ble_hs.h" -#include "services/ias/ble_svc_ias.h" +#include "nimble/porting/nimble/include/sysinit/sysinit.h" +#include "nimble/nimble/host/include/host/ble_hs.h" +#include "../include/services/ias/ble_svc_ias.h" /* Callback function */ static ble_svc_ias_event_fn *ble_svc_ias_cb_fn; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ias/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ias/syscfg.yml new file mode 100644 index 000000000..2cbed3ab4 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ias/syscfg.yml @@ -0,0 +1,23 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +syscfg.defs: + BLE_SVC_IAS_SYSINIT_STAGE: + description: > + Sysinit stage for the immediate alert BLE service. + value: 303 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/services/ipss/ble_svc_ipss.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ipss/include/services/ipss/ble_svc_ipss.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/services/ipss/ble_svc_ipss.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ipss/include/services/ipss/ble_svc_ipss.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ipss/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ipss/pkg.yml new file mode 100644 index 000000000..55be157d9 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ipss/pkg.yml @@ -0,0 +1,35 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: nimble/host/services/ipss +pkg.description: Implements the IPSS service for IPSP suppoort. +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - ble + - bluetooth + - nimble + - ipsp + - ipss + +pkg.deps: + - nimble/host + +pkg.init: + ble_svc_ipss_init: 'MYNEWT_VAL(BLE_SVC_IPSS_SYSINIT_STAGE)' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/ipss/src/ble_svc_ipss.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ipss/src/ble_svc_ipss.c similarity index 89% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/ipss/src/ble_svc_ipss.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ipss/src/ble_svc_ipss.c index f42ca1e9e..dd9d4ee96 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/ipss/src/ble_svc_ipss.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ipss/src/ble_svc_ipss.c @@ -19,9 +19,9 @@ #include -#include "sysinit/sysinit.h" -#include "host/ble_hs.h" -#include "services/ipss/ble_svc_ipss.h" +#include "nimble/porting/nimble/include/sysinit/sysinit.h" +#include "nimble/nimble/host/include/host/ble_hs.h" +#include "../include/services/ipss/ble_svc_ipss.h" static const struct ble_gatt_svc_def ble_svc_ipss_defs[] = { { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ipss/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ipss/syscfg.yml new file mode 100644 index 000000000..dd89608e3 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/ipss/syscfg.yml @@ -0,0 +1,24 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +syscfg.defs: + BLE_SVC_IPSS_SYSINIT_STAGE: + description: > + Sysinit stage for the IPSS BLE service + value: 303 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/services/lls/ble_svc_lls.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/lls/include/services/lls/ble_svc_lls.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/services/lls/ble_svc_lls.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/lls/include/services/lls/ble_svc_lls.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/lls/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/lls/pkg.yml new file mode 100644 index 000000000..6160f020e --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/lls/pkg.yml @@ -0,0 +1,34 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: nimble/host/services/lls +pkg.description: Link Loss Service Implementation. +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - ble + - bluetooth + - lls + - nimble + +pkg.deps: + - nimble/host + +pkg.init: + ble_svc_lls_init: 'MYNEWT_VAL(BLE_SVC_LLS_SYSINIT_STAGE)' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/lls/src/ble_svc_lls.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/lls/src/ble_svc_lls.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/lls/src/ble_svc_lls.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/lls/src/ble_svc_lls.c index b5f7f9bd4..822f72ece 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/lls/src/ble_svc_lls.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/lls/src/ble_svc_lls.c @@ -19,9 +19,9 @@ #include #include -#include "sysinit/sysinit.h" -#include "host/ble_hs.h" -#include "services/lls/ble_svc_lls.h" +#include "nimble/porting/nimble/include/sysinit/sysinit.h" +#include "nimble/nimble/host/include/host/ble_hs.h" +#include "../include/services/lls/ble_svc_lls.h" /* Callback function */ static ble_svc_lls_event_fn *ble_svc_lls_cb_fn; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/lls/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/lls/syscfg.yml new file mode 100644 index 000000000..312b08a2f --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/lls/syscfg.yml @@ -0,0 +1,22 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +syscfg.defs: + BLE_SVC_LLS_SYSINIT_STAGE: + description: > + Sysinit stage for the link loss BLE service. + value: 303 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/services/tps/ble_svc_tps.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/tps/include/services/tps/ble_svc_tps.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/services/tps/ble_svc_tps.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/tps/include/services/tps/ble_svc_tps.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/tps/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/tps/pkg.yml new file mode 100644 index 000000000..3d4c5e98e --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/tps/pkg.yml @@ -0,0 +1,34 @@ + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: nimble/host/services/tps +pkg.description: Tx Power Service adopted specification. +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - ble + - bluetooth + - tps + - nimble + +pkg.deps: + - nimble/host + +pkg.init: + ble_svc_tps_init: 'MYNEWT_VAL(BLE_SVC_TPS_SYSINIT_STAGE)' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_svc_tps.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/tps/src/ble_svc_tps.c similarity index 91% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_svc_tps.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/tps/src/ble_svc_tps.c index 9885a9216..0099a9689 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_svc_tps.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/tps/src/ble_svc_tps.c @@ -19,16 +19,16 @@ #include #include -#include "sysinit/sysinit.h" -#include "syscfg/syscfg.h" -#include "host/ble_hs.h" -#include "services/tps/ble_svc_tps.h" +#include "nimble/porting/nimble/include/sysinit/sysinit.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/nimble/host/include/host/ble_hs.h" +#include "../include/services/tps/ble_svc_tps.h" /* XXX: We shouldn't be including the host's private header files. The host * API needs to be updated with a function to query the advertising transmit * power. */ -#include "../src/ble_hs_hci_priv.h" +#include "nimble/nimble/host/src/ble_hs_hci_priv.h" int8_t ble_svc_tps_tx_power_level; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/tps/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/tps/syscfg.yml new file mode 100644 index 000000000..0391e8b1d --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/tps/syscfg.yml @@ -0,0 +1,23 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +syscfg.defs: + BLE_SVC_TPS_SYSINIT_STAGE: + description: > + Sysinit stage for the transmit power BLE service. + value: 303 + diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att.c similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att.c diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_clt.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_clt.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_clt.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_clt.c index 09fc9ea23..2416ecbcb 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_clt.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_clt.c @@ -21,9 +21,9 @@ #include #include #include -#include "os/os_mempool.h" -#include "nimble/ble.h" -#include "host/ble_uuid.h" +#include "nimble/porting/nimble/include/os/os_mempool.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/host/include/host/ble_uuid.h" #include "ble_hs_priv.h" /***************************************************************************** diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_cmd.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_cmd.c index 81b070f9c..4c3af1f60 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_cmd.c @@ -19,11 +19,11 @@ #include #include -#include "os/os.h" -#include "nimble/ble.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/nimble/include/nimble/ble.h" #include "ble_hs_priv.h" -#include "host/ble_att.h" -#include "host/ble_uuid.h" +#include "nimble/nimble/host/include/host/ble_att.h" +#include "nimble/nimble/host/include/host/ble_uuid.h" #include "ble_hs_priv.h" void * diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_cmd_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_cmd_priv.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_cmd_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_cmd_priv.h index 70f33260a..18f473603 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_cmd_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_cmd_priv.h @@ -22,7 +22,7 @@ #include #include -#include "os/os_mbuf.h" +#include "nimble/porting/nimble/include/os/os_mbuf.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_priv.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_priv.h index 73b6aeab0..ab59c4f01 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_priv.h @@ -21,10 +21,10 @@ #define H_BLE_ATT_PRIV_ #include -#include "stats/stats.h" -#include "host/ble_att.h" -#include "host/ble_uuid.h" -#include "nimble/nimble_npl.h" +#include "nimble/porting/nimble/include/stats/stats.h" +#include "nimble/nimble/host/include/host/ble_att.h" +#include "nimble/nimble/host/include/host/ble_uuid.h" +#include "nimble/nimble/include/nimble/nimble_npl.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_svr.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_svr.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_svr.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_svr.c index afcf90372..73172ef73 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_att_svr.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_svr.c @@ -20,11 +20,14 @@ #include #include #include -#include "os/os.h" -#include "nimble/ble.h" -#include "host/ble_uuid.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/host/include/host/ble_uuid.h" #include "ble_hs_priv.h" -#include "esp_nimble_mem.h" + +#ifdef ESP_PLATFORM +#include "nimble/esp_port/port/include/esp_nimble_mem.h" +#endif /** * ATT server - Attribute Protocol @@ -2669,7 +2672,11 @@ ble_att_svr_reset(void) static void ble_att_svr_free_start_mem(void) { +#ifdef ESP_PLATFORM nimble_platform_mem_free(ble_att_svr_entry_mem); +#else + free(ble_att_svr_entry_mem); +#endif ble_att_svr_entry_mem = NULL; } @@ -2681,7 +2688,11 @@ ble_att_svr_start(void) ble_att_svr_free_start_mem(); if (ble_hs_max_attrs > 0) { +#ifdef ESP_PLATFORM ble_att_svr_entry_mem = nimble_platform_mem_malloc( +#else + ble_att_svr_entry_mem = malloc( +#endif OS_MEMPOOL_BYTES(ble_hs_max_attrs, sizeof (struct ble_att_svr_entry))); if (ble_att_svr_entry_mem == NULL) { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_eddystone.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_eddystone.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_eddystone.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_eddystone.c index eccb3e988..ad0f449df 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_eddystone.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_eddystone.c @@ -18,9 +18,9 @@ */ #include -#include "os/endian.h" -#include "host/ble_eddystone.h" -#include "host/ble_hs_adv.h" +#include "nimble/porting/nimble/include/os/endian.h" +#include "../include/host/ble_eddystone.h" +#include "nimble/nimble/host/include/host/ble_hs_adv.h" #include "ble_hs_priv.h" #define BLE_EDDYSTONE_MAX_SVC_DATA_LEN 22 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gap.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gap.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gap.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gap.c index 17ff4eae0..068414bbf 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gap.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gap.c @@ -20,9 +20,9 @@ #include #include #include -#include "nimble/nimble_opt.h" -#include "host/ble_hs_adv.h" -#include "host/ble_hs_hci.h" +#include "nimble/nimble/include/nimble/nimble_opt.h" +#include "nimble/nimble/host/include/host/ble_hs_adv.h" +#include "nimble/nimble/host/include/host/ble_hs_hci.h" #include "ble_hs_priv.h" #include "ble_hs_resolv_priv.h" @@ -2246,11 +2246,6 @@ ble_gap_wl_set(const ble_addr_t *addrs, uint8_t white_list_count) ble_hs_lock(); - if (white_list_count == 0) { - rc = BLE_HS_EINVAL; - goto done; - } - for (i = 0; i < white_list_count; i++) { if (addrs[i].type != BLE_ADDR_PUBLIC && addrs[i].type != BLE_ADDR_RANDOM) { @@ -5617,6 +5612,11 @@ done: #endif } +int ble_gap_set_data_len(uint16_t conn_handle, uint16_t tx_octets, uint16_t tx_time) +{ + return ble_hs_hci_util_set_data_len(conn_handle, tx_octets, tx_time); +} + /***************************************************************************** * $security * *****************************************************************************/ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gap_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gap_priv.h similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gap_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gap_priv.h index 2b6b40696..3767ddba8 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gap_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gap_priv.h @@ -21,9 +21,9 @@ #define H_BLE_GAP_CONN_ #include -#include "syscfg/syscfg.h" -#include "stats/stats.h" -#include "host/ble_gap.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/stats/stats.h" +#include "nimble/nimble/host/include/host/ble_gap.h" #ifdef __cplusplus extern "C" { #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_gatt_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gatt_priv.h similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_gatt_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gatt_priv.h index 4a59635b8..07616d011 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/ble_gatt_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gatt_priv.h @@ -20,9 +20,9 @@ #ifndef H_BLE_GATT_PRIV_ #define H_BLE_GATT_PRIV_ -#include "syscfg/syscfg.h" -#include "stats/stats.h" -#include "host/ble_gatt.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/stats/stats.h" +#include "nimble/nimble/host/include/host/ble_gatt.h" #ifdef __cplusplus extern "C" { #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gattc.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gattc.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gattc.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gattc.c index a6e114cc2..f7bc9f47f 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gattc.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gattc.c @@ -54,10 +54,10 @@ #include #include #include -#include "os/os_mempool.h" -#include "nimble/ble.h" -#include "host/ble_uuid.h" -#include "host/ble_gap.h" +#include "nimble/porting/nimble/include/os/os_mempool.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/host/include/host/ble_uuid.h" +#include "nimble/nimble/host/include/host/ble_gap.h" #include "ble_hs_priv.h" /***************************************************************************** diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gatts.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gatts.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gatts.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gatts.c index e53cc116f..c805d2ab2 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gatts.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gatts.c @@ -20,11 +20,14 @@ #include #include #include -#include "nimble/ble.h" -#include "host/ble_uuid.h" -#include "host/ble_store.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/host/include/host/ble_uuid.h" +#include "nimble/nimble/host/include/host/ble_store.h" #include "ble_hs_priv.h" -#include "esp_nimble_mem.h" + +#ifdef ESP_PLATFORM +#include "nimble/esp_port/port/include/esp_nimble_mem.h" +#endif #define BLE_GATTS_INCLUDE_SZ 6 #define BLE_GATTS_CHR_MAX_SZ 19 @@ -1155,7 +1158,11 @@ ble_gatts_connection_broken(uint16_t conn_handle) static void ble_gatts_free_svc_defs(void) { +#ifdef ESP_PLATFORM nimble_platform_mem_free(ble_gatts_svc_defs); +#else + free(ble_gatts_svc_defs); +#endif ble_gatts_svc_defs = NULL; ble_gatts_num_svc_defs = 0; } @@ -1163,11 +1170,19 @@ ble_gatts_free_svc_defs(void) static void ble_gatts_free_mem(void) { +#ifdef ESP_PLATFORM nimble_platform_mem_free(ble_gatts_clt_cfg_mem); ble_gatts_clt_cfg_mem = NULL; nimble_platform_mem_free(ble_gatts_svc_entries); ble_gatts_svc_entries = NULL; +#else + free(ble_gatts_clt_cfg_mem); + ble_gatts_clt_cfg_mem = NULL; + + free(ble_gatts_svc_entries); + ble_gatts_svc_entries = NULL; +#endif } @@ -1210,7 +1225,11 @@ ble_gatts_start(void) } if (ble_hs_max_client_configs > 0) { +#ifdef ESP_PLATFORM ble_gatts_clt_cfg_mem = nimble_platform_mem_malloc( +#else + ble_gatts_clt_cfg_mem = malloc( +#endif OS_MEMPOOL_BYTES(ble_hs_max_client_configs, sizeof (struct ble_gatts_clt_cfg))); if (ble_gatts_clt_cfg_mem == NULL) { @@ -1221,7 +1240,11 @@ ble_gatts_start(void) if (ble_hs_max_services > 0) { ble_gatts_svc_entries = +#ifdef ESP_PLATFORM nimble_platform_mem_malloc(ble_hs_max_services * sizeof *ble_gatts_svc_entries); +#else + malloc(ble_hs_max_services * sizeof *ble_gatts_svc_entries); +#endif if (ble_gatts_svc_entries == NULL) { rc = BLE_HS_ENOMEM; goto done; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gatts_lcl.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gatts_lcl.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gatts_lcl.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gatts_lcl.c index a45f397bc..989eb5c27 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_gatts_lcl.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gatts_lcl.c @@ -19,9 +19,9 @@ #include #include -#include "host/ble_uuid.h" -#include "console/console.h" -#include "nimble/ble.h" +#include "nimble/nimble/host/include/host/ble_uuid.h" +#include "nimble/console/console.h" +#include "nimble/nimble/include/nimble/ble.h" #include "ble_hs_priv.h" static const ble_uuid_t *uuid_ccc = diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs.c index d819e20df..4a7087b15 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs.c @@ -20,15 +20,15 @@ #include #include #include -#include "sysinit/sysinit.h" -#include "syscfg/syscfg.h" -#include "stats/stats.h" -#include "nimble/ble_hci_trans.h" +#include "nimble/porting/nimble/include/sysinit/sysinit.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/stats/stats.h" +#include "nimble/nimble/include/nimble/ble_hci_trans.h" #include "ble_hs_priv.h" #include "ble_monitor_priv.h" -#include "nimble/nimble_npl.h" +#include "nimble/nimble/include/nimble/nimble_npl.h" #ifndef MYNEWT -#include "nimble/nimble_port.h" +#include "nimble/porting/nimble/include/nimble/nimble_port.h" #endif #define BLE_HS_HCI_EVT_COUNT \ @@ -86,8 +86,10 @@ uint16_t ble_hs_max_services; uint16_t ble_hs_max_client_configs; #if MYNEWT_VAL(BLE_HS_DEBUG) +#ifdef ESP_PLATFORM static uint8_t ble_hs_mutex_locked; static TaskHandle_t ble_hs_task_handle; +#endif static uint8_t ble_hs_dbg_mutex_locked; #endif @@ -131,8 +133,10 @@ ble_hs_locked_by_cur_task(void) owner = ble_hs_mutex.mu.mu_owner; return owner != NULL && owner == os_sched_get_current_task(); -#else +#elif ESP_PLATFORM return (ble_hs_mutex_locked && ble_hs_task_handle == xTaskGetCurrentTaskHandle()); +#else + return 1; #endif } #endif @@ -164,7 +168,7 @@ ble_hs_lock_nested(void) rc = ble_npl_mutex_pend(&ble_hs_mutex, 0xffffffff); -#if MYNEWT_VAL(BLE_HS_DEBUG) +#if MYNEWT_VAL(BLE_HS_DEBUG) && defined(ESP_PLATFORM) ble_hs_mutex_locked = 1; ble_hs_task_handle = xTaskGetCurrentTaskHandle(); #endif @@ -184,10 +188,12 @@ ble_hs_unlock_nested(void) ble_hs_dbg_mutex_locked = 0; return; } +#ifdef ESP_PLATFORM if(ble_hs_task_handle == xTaskGetCurrentTaskHandle()) { ble_hs_task_handle = NULL; ble_hs_mutex_locked = 0; } +#endif #endif rc = ble_npl_mutex_release(&ble_hs_mutex); diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_adv.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_adv.c index 1d938b958..1fe183977 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_adv.c @@ -19,8 +19,8 @@ #include #include -#include "nimble/ble.h" -#include "host/ble_hs_adv.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/host/include/host/ble_hs_adv.h" #include "ble_hs_priv.h" struct find_field_data { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_adv_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_adv_priv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_adv_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_adv_priv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_atomic.c similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_atomic.c diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_atomic_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_atomic_priv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_atomic_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_atomic_priv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_cfg.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_cfg.c similarity index 92% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_cfg.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_cfg.c index a46a604ac..0569ccee8 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_cfg.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_cfg.c @@ -17,8 +17,8 @@ * under the License. */ -#include "syscfg/syscfg.h" -#include "host/ble_hs.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/nimble/host/include/host/ble_hs.h" struct ble_hs_cfg ble_hs_cfg = { /** Security manager settings. */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_conn.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_conn.c index 31830c98a..1625e7305 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_conn.c @@ -19,9 +19,9 @@ #include #include -#include "syscfg/syscfg.h" -#include "os/os.h" -#include "host/ble_hs_id.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/nimble/host/include/host/ble_hs_id.h" #include "ble_hs_priv.h" #include "ble_hs_resolv_priv.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_conn_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_conn_priv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_conn_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_conn_priv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_flow.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_flow.c index 2520c8541..e74f5da36 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_flow.c @@ -17,8 +17,8 @@ * under the License. */ -#include "syscfg/syscfg.h" -#include "nimble/ble_hci_trans.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/nimble/include/nimble/ble_hci_trans.h" #include "ble_hs_priv.h" #if MYNEWT_VAL(BLE_HS_FLOW_CTRL) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_flow_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_flow_priv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_flow_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_flow_priv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci.c index 3cfed27e2..214fc8214 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci.c @@ -20,10 +20,10 @@ #include #include #include -#include "os/os.h" -#include "mem/mem.h" -#include "nimble/ble_hci_trans.h" -#include "host/ble_monitor.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/porting/nimble/include/mem/mem.h" +#include "nimble/nimble/include/nimble/ble_hci_trans.h" +#include "nimble/nimble/host/include/host/ble_monitor.h" #include "ble_hs_priv.h" #include "ble_monitor_priv.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_cmd.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_cmd.c similarity index 79% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_cmd.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_cmd.c index 7aa9e4e74..63242ca88 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_cmd.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_cmd.c @@ -21,24 +21,13 @@ #include #include #include -#include "os/os.h" -#include "nimble/hci_common.h" -#include "nimble/ble_hci_trans.h" -#include "host/ble_monitor.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/nimble/include/nimble/hci_common.h" +#include "nimble/nimble/include/nimble/ble_hci_trans.h" +#include "nimble/nimble/host/include/host/ble_monitor.h" #include "ble_hs_priv.h" #include "ble_monitor_priv.h" -/* - * HCI Command Header - * - * Comprises the following fields - * -> Opcode group field & Opcode command field (2) - * -> Parameter Length (1) - * Length of all the parameters (does not include any part of the hci - * command header - */ -#define BLE_HCI_CMD_HDR_LEN (3) - static int ble_hs_hci_cmd_transport(struct ble_hci_cmd *cmd) { @@ -62,6 +51,18 @@ ble_hs_hci_cmd_transport(struct ble_hci_cmd *cmd) } } +#ifdef ESP_PLATFORM +/* + * HCI Command Header + * + * Comprises the following fields + * -> Opcode group field & Opcode command field (2) + * -> Parameter Length (1) + * Length of all the parameters (does not include any part of the hci + * command header + */ +#define BLE_HCI_CMD_HDR_LEN (3) + static int ble_hs_hci_cmd_send(uint16_t opcode, uint8_t len, const void *cmddata) { @@ -98,6 +99,34 @@ ble_hs_hci_cmd_send(uint16_t opcode, uint8_t len, const void *cmddata) return rc; } +#else +static int +ble_hs_hci_cmd_send(uint16_t opcode, uint8_t len, const void *cmddata) +{ + struct ble_hci_cmd *cmd; + int rc; + + cmd = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD); + BLE_HS_DBG_ASSERT(cmd != NULL); + + cmd->opcode = htole16(opcode); + cmd->length = len; + if (len != 0) { + memcpy(cmd->data, cmddata, len); + } + + rc = ble_hs_hci_cmd_transport(cmd); + + if (rc == 0) { + STATS_INC(ble_hs_stats, hci_cmd); + } else { + BLE_HS_LOG(DEBUG, "ble_hs_hci_cmd_send failure; rc=%d\n", rc); + } + + return rc; +} +#endif + int ble_hs_hci_cmd_send_buf(uint16_t opcode, const void *buf, uint8_t buf_len) { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_evt.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_evt.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_evt.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_evt.c index 4a6b0716e..9b97f433b 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_evt.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_evt.c @@ -20,11 +20,11 @@ #include #include #include -#include "os/os.h" -#include "nimble/hci_common.h" -#include "nimble/ble_hci_trans.h" -#include "host/ble_gap.h" -#include "host/ble_monitor.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/nimble/include/nimble/hci_common.h" +#include "nimble/nimble/include/nimble/ble_hci_trans.h" +#include "nimble/nimble/host/include/host/ble_gap.h" +#include "nimble/nimble/host/include/host/ble_monitor.h" #include "ble_hs_priv.h" #include "ble_hs_resolv_priv.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_hs_hci_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_priv.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_hs_hci_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_priv.h index 362f12cbd..d8a72cb29 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_hs_hci_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_priv.h @@ -20,7 +20,7 @@ #ifndef H_BLE_HS_HCI_PRIV_ #define H_BLE_HS_HCI_PRIV_ -#include "nimble/hci_common.h" +#include "nimble/nimble/include/nimble/hci_common.h" #ifdef __cplusplus extern "C" { #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_util.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_util.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_util.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_util.c index 996e0fc10..1f63acc94 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_util.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_util.c @@ -18,8 +18,8 @@ */ #include -#include "nimble/hci_common.h" -#include "host/ble_hs_hci.h" +#include "nimble/nimble/include/nimble/hci_common.h" +#include "nimble/nimble/host/include/host/ble_hs_hci.h" #include "ble_hs_priv.h" uint16_t diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_id.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_id.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_id.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_id.c index e30a3a1bc..83ee49393 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_id.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_id.c @@ -18,7 +18,7 @@ */ #include -#include "host/ble_hs_id.h" +#include "nimble/nimble/host/include/host/ble_hs_id.h" #include "ble_hs_priv.h" #include "ble_hs_resolv_priv.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_id_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_id_priv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_id_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_id_priv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_log.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_log.c similarity index 92% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_log.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_log.c index 7ec69469e..b4d496703 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_log.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_log.c @@ -17,8 +17,8 @@ * under the License. */ -#include "os/os.h" -#include "host/ble_hs.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/nimble/host/include/host/ble_hs.h" struct log ble_hs_log; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_mbuf.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_mbuf.c index ea660c633..680fbe38a 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_mbuf.c @@ -17,7 +17,7 @@ * under the License. */ -#include "host/ble_hs.h" +#include "nimble/nimble/host/include/host/ble_hs.h" #include "ble_hs_priv.h" /** diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_mbuf_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_mbuf_priv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_mbuf_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_mbuf_priv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_misc.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_misc.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_misc.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_misc.c index dfb46b741..b9567f382 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_misc.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_misc.c @@ -19,7 +19,7 @@ #include #include -#include "os/os.h" +#include "nimble/porting/nimble/include/os/os.h" #include "ble_hs_priv.h" const uint8_t ble_hs_misc_null_addr[6]; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_mqueue.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_mqueue.c similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_mqueue.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_mqueue.c diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_periodic_sync.c similarity index 95% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_periodic_sync.c index dad535138..05a928201 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_periodic_sync.c @@ -19,9 +19,9 @@ #include #include -#include "syscfg/syscfg.h" -#include "os/os.h" -#include "host/ble_hs_id.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/nimble/host/include/host/ble_hs_id.h" #include "ble_hs_priv.h" #if MYNEWT_VAL(BLE_PERIODIC_ADV) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_periodic_sync_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_periodic_sync_priv.h similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_periodic_sync_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_periodic_sync_priv.h index c82ea7904..f16132f04 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_periodic_sync_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_periodic_sync_priv.h @@ -21,7 +21,7 @@ #define H_BLE_HS_PERIODIC_SYNC_ #include -#include "os/queue.h" +#include "nimble/porting/nimble/include/os/queue.h" #ifdef __cplusplus extern "C" { #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_priv.h similarity index 95% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_priv.h index 538d07a97..952690e71 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_priv.h @@ -42,10 +42,10 @@ #include "ble_hs_id_priv.h" #include "ble_hs_periodic_sync_priv.h" #include "ble_uuid_priv.h" -#include "host/ble_hs.h" -#include "host/ble_monitor.h" -#include "nimble/nimble_opt.h" -#include "stats/stats.h" +#include "nimble/nimble/host/include/host/ble_hs.h" +#include "nimble/nimble/host/include/host/ble_monitor.h" +#include "nimble/nimble/include/nimble/nimble_opt.h" +#include "nimble/porting/nimble/include/stats/stats.h" #ifdef __cplusplus extern "C" { #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_pvcy.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_pvcy.c index 9e92c660f..2d7db0bcc 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_pvcy.c @@ -19,10 +19,10 @@ #include #include #include -#include "stats/stats.h" +#include "nimble/porting/nimble/include/stats/stats.h" #include "ble_hs_priv.h" #include "ble_hs_resolv_priv.h" -#include "host/ble_hs_pvcy.h" +#include "nimble/nimble/host/include/host/ble_hs_pvcy.h" static uint8_t ble_hs_pvcy_started; static uint8_t ble_hs_pvcy_irk[16]; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_pvcy_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_pvcy_priv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_pvcy_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_pvcy_priv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_resolv.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_resolv.c index 6add1018b..7ae9ef12b 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_resolv.c @@ -19,17 +19,17 @@ * under the License. */ -#include "syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" #if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY) #include #include #include "ble_hs_priv.h" -#include "host/ble_hs_id.h" -#include "nimble/ble.h" -#include "nimble/nimble_opt.h" +#include "../include/host/ble_hs_id.h" +#include "../../include/nimble/ble.h" +#include "../../include/nimble/nimble_opt.h" #include "ble_hs_resolv_priv.h" -#include "store/config/ble_store_config.h" +#include "../store/config/include/store/config/ble_store_config.h" #include "../store/config/src/ble_store_config_priv.h" /* Resolve list size, additional space to save local device's configuration */ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_resolv_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_resolv_priv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_resolv_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_resolv_priv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_shutdown.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_shutdown.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_shutdown.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_shutdown.c index f29d4a669..9dacccbaf 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_shutdown.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_shutdown.c @@ -19,7 +19,7 @@ #if MYNEWT -#include "os/mynewt.h" +#include "nimble/porting/nimble/include/os/mynewt.h" #include "ble_hs_priv.h" static struct ble_hs_stop_listener ble_hs_shutdown_stop_listener; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_startup.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_startup.c index 83026ac18..2ec17a13b 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_startup.c @@ -19,8 +19,8 @@ #include #include -#include "host/ble_hs.h" -#include "host/ble_hs_hci.h" +#include "nimble/nimble/host/include/host/ble_hs.h" +#include "nimble/nimble/host/include/host/ble_hs_hci.h" #include "ble_hs_priv.h" #if !MYNEWT_VAL(BLE_CONTROLLER) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_startup_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_startup_priv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_startup_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_startup_priv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_stop.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_stop.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_stop.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_stop.c index b90d3ec6f..92fae1263 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_stop.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_stop.c @@ -18,12 +18,12 @@ */ #include -#include "sysinit/sysinit.h" -#include "syscfg/syscfg.h" +#include "nimble/porting/nimble/include/sysinit/sysinit.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" #include "ble_hs_priv.h" -#include "nimble/nimble_npl.h" +#include "nimble/nimble/include/nimble/nimble_npl.h" #ifndef MYNEWT -#include "nimble/nimble_port.h" +#include "nimble/porting/nimble/include/nimble/nimble_port.h" #endif #define BLE_HOST_STOP_TIMEOUT_MS MYNEWT_VAL(BLE_HS_STOP_ON_SHUTDOWN_TIMEOUT) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_ibeacon.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_ibeacon.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_ibeacon.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_ibeacon.c index 0c6ef99d5..62c7bc1d1 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_ibeacon.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_ibeacon.c @@ -18,7 +18,7 @@ */ #include -#include "host/ble_hs_adv.h" +#include "nimble/nimble/host/include/host/ble_hs_adv.h" #include "ble_hs_priv.h" #define BLE_IBEACON_MFG_DATA_SIZE 25 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap.c index 0d9f082d4..a4b98a9e7 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap.c @@ -19,10 +19,10 @@ #include #include -#include "syscfg/syscfg.h" -#include "os/os.h" -#include "nimble/ble.h" -#include "nimble/hci_common.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/include/nimble/hci_common.h" #include "ble_hs_priv.h" #include "ble_l2cap_coc_priv.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_coc.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_coc.c index 41a831565..5258da84d 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_coc.c @@ -19,7 +19,7 @@ #include #include -#include "nimble/ble.h" +#include "nimble/nimble/include/nimble/ble.h" #include "ble_hs_priv.h" #include "ble_l2cap_priv.h" #include "ble_l2cap_coc_priv.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_coc_priv.h similarity index 93% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_coc_priv.h index 5ebdaa050..911946e05 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_coc_priv.h @@ -21,10 +21,10 @@ #define H_L2CAP_COC_PRIV_ #include -#include "syscfg/syscfg.h" -#include "os/queue.h" -#include "os/os_mbuf.h" -#include "host/ble_l2cap.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/os/queue.h" +#include "nimble/porting/nimble/include/os/os_mbuf.h" +#include "nimble/nimble/host/include/host/ble_l2cap.h" #include "ble_l2cap_sig_priv.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_priv.h similarity index 95% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_priv.h index e3409743b..30af30427 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_priv.h @@ -21,11 +21,11 @@ #define H_L2CAP_PRIV_ #include "ble_l2cap_coc_priv.h" -#include "host/ble_l2cap.h" +#include "nimble/nimble/host/include/host/ble_l2cap.h" #include -#include "stats/stats.h" -#include "os/queue.h" -#include "os/os_mbuf.h" +#include "nimble/porting/nimble/include/stats/stats.h" +#include "nimble/porting/nimble/include/os/queue.h" +#include "nimble/porting/nimble/include/os/os_mbuf.h" #ifdef __cplusplus extern "C" { #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_sig.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_sig.c index 58f96b0f3..f9d32d0ac 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_sig.c @@ -44,8 +44,8 @@ #include #include -#include "nimble/ble.h" -#include "host/ble_monitor.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/host/include/host/ble_monitor.h" #include "ble_hs_priv.h" /***************************************************************************** diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_cmd.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_sig_cmd.c similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_cmd.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_sig_cmd.c diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_sig_priv.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_sig_priv.h index a698cd0d8..a0e2e58cf 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_sig_priv.h @@ -20,7 +20,7 @@ #ifndef H_BLE_L2CAP_SIG_ #define H_BLE_L2CAP_SIG_ -#include "syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_monitor.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_monitor.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_monitor.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_monitor.c index e6db48b82..d4a468284 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_monitor.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_monitor.c @@ -17,7 +17,7 @@ * under the License. */ -#include "host/ble_monitor.h" +#include "nimble/nimble/host/include/host/ble_monitor.h" #if BLE_MONITOR @@ -28,10 +28,10 @@ #include #include #include -#include "os/os.h" -#include "log/log.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/porting/nimble/include/log/log.h" #if MYNEWT_VAL(BLE_MONITOR_UART) -#include "uart/uart.h" +#include "nimble/porting/nimble/include/uart/uart.h" #endif #if MYNEWT_VAL(BLE_MONITOR_RTT) #include "rtt/SEGGER_RTT.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_monitor_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_monitor_priv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_monitor_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_monitor_priv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm.c index 8422c044f..acbe8a1c1 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm.c @@ -43,9 +43,9 @@ #include #include -#include "nimble/ble.h" -#include "nimble/nimble_opt.h" -#include "host/ble_sm.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/include/nimble/nimble_opt.h" +#include "nimble/nimble/host/include/host/ble_sm.h" #include "ble_hs_priv.h" #include "ble_hs_resolv_priv.h" #include "../store/config/src/ble_store_config_priv.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_alg.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_alg.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_alg.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_alg.c index ee8b937c5..e17760efe 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_alg.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_alg.c @@ -20,12 +20,12 @@ #include #include -#include "syscfg/syscfg.h" -#include "nimble/nimble_opt.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/nimble/include/nimble/nimble_opt.h" #if NIMBLE_BLE_SM -#include "nimble/ble.h" +#include "nimble/nimble/include/nimble/ble.h" #include "ble_hs_priv.h" #if MYNEWT_VAL(BLE_CRYPTO_STACK_MBEDTLS) @@ -41,13 +41,13 @@ #endif #else -#include "tinycrypt/aes.h" -#include "tinycrypt/constants.h" -#include "tinycrypt/utils.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/aes.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/constants.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/utils.h" #if MYNEWT_VAL(BLE_SM_SC) -#include "tinycrypt/cmac_mode.h" -#include "tinycrypt/ecc_dh.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/cmac_mode.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/ecc_dh.h" #if MYNEWT_VAL(TRNG) #include "trng/trng.h" #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_cmd.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_cmd.c similarity index 92% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_cmd.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_cmd.c index 01651f1df..92a34ed36 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_cmd.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_cmd.c @@ -19,9 +19,9 @@ #include #include -#include "nimble/ble.h" -#include "nimble/nimble_opt.h" -#include "host/ble_sm.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/include/nimble/nimble_opt.h" +#include "nimble/nimble/host/include/host/ble_sm.h" #include "ble_hs_priv.h" void * diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_lgcy.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_lgcy.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_lgcy.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_lgcy.c index bb2d66d5d..2f150eeb3 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_lgcy.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_lgcy.c @@ -19,9 +19,9 @@ #include #include -#include "nimble/ble.h" -#include "nimble/nimble_opt.h" -#include "host/ble_sm.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/include/nimble/nimble_opt.h" +#include "nimble/nimble/host/include/host/ble_sm.h" #include "ble_hs_priv.h" #if MYNEWT_VAL(BLE_SM_LEGACY) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_priv.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_priv.h index def0a32f5..853b33f7a 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_priv.h @@ -21,9 +21,9 @@ #define H_BLE_SM_PRIV_ #include -#include "syscfg/syscfg.h" -#include "os/queue.h" -#include "nimble/nimble_opt.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/os/queue.h" +#include "nimble/nimble/include/nimble/nimble_opt.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_sc.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_sc.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_sc.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_sc.c index 333310702..ffc807fa6 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_sm_sc.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_sc.c @@ -19,8 +19,8 @@ #include -#include "nimble/nimble_opt.h" -#include "host/ble_sm.h" +#include "nimble/nimble/include/nimble/nimble_opt.h" +#include "nimble/nimble/host/include/host/ble_sm.h" #include "ble_hs_priv.h" #include "ble_sm_priv.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_store.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_store.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_store.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_store.c index 22e608947..e5a475530 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_store.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_store.c @@ -19,7 +19,7 @@ #include -#include "host/ble_store.h" +#include "nimble/nimble/host/include/host/ble_store.h" #include "ble_hs_priv.h" int diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_store_util.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_store_util.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_store_util.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_store_util.c index 73c71d93b..033261242 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_store_util.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_store_util.c @@ -17,7 +17,7 @@ * under the License. */ -#include "host/ble_store.h" +#include "nimble/nimble/host/include/host/ble_store.h" #include "ble_hs_priv.h" #include "ble_hs_resolv_priv.h" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_uuid.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_uuid.c similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_uuid.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_uuid.c index 3a1642480..1b2443683 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_uuid.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_uuid.c @@ -22,10 +22,10 @@ #include #include #include -#include "os/os_mbuf.h" -#include "nimble/ble.h" +#include "nimble/porting/nimble/include/os/os_mbuf.h" +#include "nimble/nimble/include/nimble/ble.h" #include "ble_hs_priv.h" -#include "host/ble_uuid.h" +#include "nimble/nimble/host/include/host/ble_uuid.h" static uint8_t ble_uuid_base[16] = { 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_uuid_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_uuid_priv.h similarity index 96% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_uuid_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_uuid_priv.h index 3dbcc6b8e..39ce88d7a 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_uuid_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_uuid_priv.h @@ -20,7 +20,7 @@ #ifndef H_BLE_UUID_PRIV_ #define H_BLE_UUID_PRIV_ -#include "host/ble_uuid.h" +#include "nimble/nimble/host/include/host/ble_uuid.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/store/config/ble_store_config.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/include/store/config/ble_store_config.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/store/config/ble_store_config.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/include/store/config/ble_store_config.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/pkg.yml new file mode 100644 index 000000000..db80d1df8 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/pkg.yml @@ -0,0 +1,38 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: nimble/host/store/config +pkg.description: sys/config-based persistence layer for the NimBLE host. +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - ble + - bluetooth + - nimble + - persistence + +pkg.deps: + - "@apache-mynewt-core/encoding/base64" + - nimble/host + +pkg.deps.BLE_STORE_CONFIG_PERSIST: + - "@apache-mynewt-core/sys/config" + +pkg.init: + ble_store_config_init: 'MYNEWT_VAL(BLE_STORE_SYSINIT_STAGE)' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/src/ble_store_config.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/src/ble_store_config.c index a2c9aaf27..4ffaaf4e1 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/src/ble_store_config.c @@ -20,10 +20,10 @@ #include #include -#include "sysinit/sysinit.h" -#include "syscfg/syscfg.h" -#include "host/ble_hs.h" -#include "store/config/ble_store_config.h" +#include "nimble/porting/nimble/include/sysinit/sysinit.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/nimble/host/include/host/ble_hs.h" +#include "../include/store/config/ble_store_config.h" #include "ble_store_config_priv.h" struct ble_store_value_sec diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/src/ble_store_config_conf.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/src/ble_store_config_conf.c new file mode 100644 index 000000000..c492c59bc --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/src/ble_store_config_conf.c @@ -0,0 +1,296 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* + * Modified work Copyright (c) 2021 Ryan Powell. + */ + +#ifndef ESP_PLATFORM + +#include "nimble/porting/nimble/include/syscfg/syscfg.h" + +#if MYNEWT_VAL(BLE_STORE_CONFIG_PERSIST) + +#include +//#include + +#include "nimble/porting/nimble/include/sysinit/sysinit.h" +#include "../../../include/host/ble_hs.h" +//#include "config/config.h" +#include "base64/base64.h" +#include "../include/store/config/ble_store_config.h" +#include "ble_store_config_priv.h" +#include "ble_bond_nvs.h" + +/* +static int +ble_store_config_conf_set(int argc, char **argv, char *val); +static int +ble_store_config_conf_export(void (*func)(char *name, char *val), + enum conf_export_tgt tgt); + +static struct conf_handler ble_store_config_conf_handler = { + .ch_name = "ble_hs", + .ch_get = NULL, + .ch_set = ble_store_config_conf_set, + .ch_commit = NULL, + .ch_export = ble_store_config_conf_export +}; +*/ +#define BLE_STORE_CONFIG_SEC_ENCODE_SZ \ + BASE64_ENCODE_SIZE(sizeof (struct ble_store_value_sec)) + +#define BLE_STORE_CONFIG_SEC_SET_ENCODE_SZ \ + (MYNEWT_VAL(BLE_STORE_MAX_BONDS) * BLE_STORE_CONFIG_SEC_ENCODE_SZ + 1) + +#define BLE_STORE_CONFIG_CCCD_ENCODE_SZ \ + BASE64_ENCODE_SIZE(sizeof (struct ble_store_value_cccd)) + +#define BLE_STORE_CONFIG_CCCD_SET_ENCODE_SZ \ + (MYNEWT_VAL(BLE_STORE_MAX_CCCDS) * BLE_STORE_CONFIG_CCCD_ENCODE_SZ + 1) + +static void +ble_store_config_serialize_arr(const void *arr, int obj_sz, int num_objs, + char *out_buf, int buf_sz) +{ + int arr_size; + + arr_size = obj_sz * num_objs; + assert(arr_size <= buf_sz); + + base64_encode(arr, arr_size, out_buf, 1); +} + +static int +ble_store_config_deserialize_arr(const char *enc, + void *out_arr, + int obj_sz, + int *out_num_objs) +{ + int len; + + len = base64_decode(enc, out_arr); + if (len < 0) { + return OS_EINVAL; + } + + *out_num_objs = len / obj_sz; + return 0; +} +/* +static int +ble_store_config_conf_set(int argc, char **argv, char *val) +{ + int rc; + + if (argc == 1) { + if (strcmp(argv[0], "our_sec") == 0) { + rc = ble_store_config_deserialize_arr( + val, + ble_store_config_our_secs, + sizeof *ble_store_config_our_secs, + &ble_store_config_num_our_secs); + printf("\nloading: %s %s rc=%d\n", *argv, val, rc); + return rc; + } else if (strcmp(argv[0], "peer_sec") == 0) { + rc = ble_store_config_deserialize_arr( + val, + ble_store_config_peer_secs, + sizeof *ble_store_config_peer_secs, + &ble_store_config_num_peer_secs); + printf("\nloading: %s %s rc=%d\n", *argv, val, rc); + return rc; + } else if (strcmp(argv[0], "cccd") == 0) { + rc = ble_store_config_deserialize_arr( + val, + ble_store_config_cccds, + sizeof *ble_store_config_cccds, + &ble_store_config_num_cccds); + printf("\nloading: %s %s rc=%d\n", *argv, val, rc); + return rc; + } + } + return OS_ENOENT; +} + +static int +ble_store_config_conf_export(void (*func)(char *name, char *val), + enum conf_export_tgt tgt) +{ + union { + char sec[BLE_STORE_CONFIG_SEC_SET_ENCODE_SZ]; + char cccd[BLE_STORE_CONFIG_CCCD_SET_ENCODE_SZ]; + } buf; + + ble_store_config_serialize_arr(ble_store_config_our_secs, + sizeof *ble_store_config_our_secs, + ble_store_config_num_our_secs, + buf.sec, + sizeof buf.sec); + func("ble_hs/our_sec", buf.sec); + + ble_store_config_serialize_arr(ble_store_config_peer_secs, + sizeof *ble_store_config_peer_secs, + ble_store_config_num_peer_secs, + buf.sec, + sizeof buf.sec); + func("ble_hs/peer_sec", buf.sec); + + ble_store_config_serialize_arr(ble_store_config_cccds, + sizeof *ble_store_config_cccds, + ble_store_config_num_cccds, + buf.cccd, + sizeof buf.cccd); + func("ble_hs/cccd", buf.cccd); + + return 0; +} +*/ +static int +ble_store_config_persist_sec_set(uint32_t setting_name, + const struct ble_store_value_sec *secs, + int num_secs) +{ + char buf[BLE_STORE_CONFIG_SEC_SET_ENCODE_SZ]; + int rc; + + ble_store_config_serialize_arr(secs, sizeof *secs, num_secs, + buf, sizeof buf); + + rc = ble_bond_nvs_save_entry(setting_name, buf); + if (rc != 0) { + return BLE_HS_ESTORE_FAIL; + } + + return 0; +} + +int +ble_store_config_persist_our_secs(void) +{ + int rc; + + rc = ble_store_config_persist_sec_set(our_sec, + ble_store_config_our_secs, + ble_store_config_num_our_secs); + if (rc != 0) { + return rc; + } + + return 0; +} + +int +ble_store_config_persist_peer_secs(void) +{ + int rc; + + rc = ble_store_config_persist_sec_set(peer_sec, + ble_store_config_peer_secs, + ble_store_config_num_peer_secs); + if (rc != 0) { + return rc; + } + + return 0; +} + +int +ble_store_config_persist_cccds(void) +{ + char buf[BLE_STORE_CONFIG_CCCD_SET_ENCODE_SZ]; + int rc; + + ble_store_config_serialize_arr(ble_store_config_cccds, + sizeof *ble_store_config_cccds, + ble_store_config_num_cccds, + buf, + sizeof buf); + + rc = ble_bond_nvs_save_entry(cccd, buf); + if (rc != 0) { + return BLE_HS_ESTORE_FAIL; + } + + return 0; +} + +void +ble_store_config_conf_init(void) +{ + uint32_t val_addr = 0; + int rc = 0; + + rc = ble_bond_nvs_get_entry(our_sec, &val_addr); + if (rc == 0) { + rc = ble_store_config_deserialize_arr( + (char*)val_addr, + ble_store_config_our_secs, + sizeof *ble_store_config_our_secs, + &ble_store_config_num_our_secs); + if (rc != 0) { + BLE_HS_LOG(ERROR, "our_sec restore error rc=%d\n", rc); + return; + } + + rc = ble_bond_nvs_get_entry(peer_sec, &val_addr); + if (rc == 0) { + rc = ble_store_config_deserialize_arr( + (char*)val_addr, + ble_store_config_peer_secs, + sizeof *ble_store_config_peer_secs, + &ble_store_config_num_peer_secs); + if (rc != 0) { + BLE_HS_LOG(ERROR, "peer_sec restore error rc=%d\n", rc); + return; + } + + } else { + /* If we have a security entry for our security but not a peer + * we should assume something wrong with the store so delete it. + */ + BLE_HS_LOG(ERROR, "peer info not found\n"); + ble_store_clear(); + return; + } + + rc = ble_bond_nvs_get_entry(cccd, &val_addr); + if (rc == 0) { + rc = ble_store_config_deserialize_arr( + (char*)val_addr, + ble_store_config_cccds, + sizeof *ble_store_config_cccds, + &ble_store_config_num_cccds); + if (rc != 0) { + BLE_HS_LOG(ERROR, "cccd restore error rc=%d\n", rc); + return; + } + } + } + + /* int rc; + + rc = conf_register(&ble_store_config_conf_handler); + SYSINIT_PANIC_ASSERT_MSG(rc == 0, + "Failed to register ble_store_config conf"); + */ +} + +#endif /* MYNEWT_VAL(BLE_STORE_CONFIG_PERSIST) */ +#endif /* ESP_PLATFORM */ \ No newline at end of file diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/src/ble_store_config_priv.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/src/ble_store_config_priv.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_nvs.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/src/ble_store_nvs.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_nvs.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/src/ble_store_nvs.c index 49ca6ed73..e09182d9f 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_nvs.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/src/ble_store_nvs.c @@ -19,16 +19,16 @@ * under the License. */ - -#include "syscfg/syscfg.h" +#ifdef ESP_PLATFORM +#include "nimble/porting/nimble/include/syscfg/syscfg.h" #if MYNEWT_VAL(BLE_STORE_CONFIG_PERSIST) #include #include -#include "sysinit/sysinit.h" -#include "host/ble_hs.h" -#include "store/config/ble_store_config.h" +#include "nimble/porting/nimble/include/sysinit/sysinit.h" +#include "../../../include/host/ble_hs.h" +#include "../include/store/config/ble_store_config.h" #include "ble_store_config_priv.h" #include "esp_log.h" #include "nvs.h" @@ -650,3 +650,4 @@ void ble_store_config_conf_init(void) /***************************************************************************************/ #endif /* MYNEWT_VAL(BLE_STORE_CONFIG_PERSIST) */ +#endif /* ESP_PLATFORM */ \ No newline at end of file diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/syscfg.yml new file mode 100644 index 000000000..ff0689c6d --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/store/config/syscfg.yml @@ -0,0 +1,27 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +syscfg.defs: + BLE_STORE_CONFIG_PERSIST: + description: > + Whether to save data to sys/config, or just keep it in RAM. + value: 1 + BLE_STORE_SYSINIT_STAGE: + description: > + Sysinit stage for BLE host store. + value: 500 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/syscfg.yml new file mode 100644 index 000000000..e72e8d529 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/syscfg.yml @@ -0,0 +1,471 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +syscfg.defs: + BLE_HOST: + description: 'Indicates that a BLE host is present.' + value: 1 + + BLE_HS_AUTO_START: + description: > + Causes the BLE host to automatically start during system + initialization. + value: 1 + + # Debug settings. + BLE_HS_DEBUG: + description: 'Enables extra runtime assertions.' + value: 0 + BLE_HS_PHONY_HCI_ACKS: + description: > + Rather than wait for HCI acknowledgements from a controller, the + host simulates incoming acks. Only recommended for test code + running in the simulator. + value: 0 + BLE_HS_REQUIRE_OS: + description: > + Specifies whether the host can depend on the kernel being present. + This should only be disabled for unit tests running in the + simulator. + value: 1 + + # Monitor interface settings + BLE_MONITOR_UART: + description: Enables monitor interface over UART + value: 0 + BLE_MONITOR_UART_DEV: + description: Monitor interface UART device + value: '"uart0"' + BLE_MONITOR_UART_BAUDRATE: + description: Baudrate for monitor interface UART + value: 1000000 + BLE_MONITOR_UART_BUFFER_SIZE: + description: > + Monitor interface ringbuffer size for UART. + This value should be a power of 2. + value: 64 + BLE_MONITOR_RTT: + description: Enables monitor interface over RTT + value: 0 + BLE_MONITOR_RTT_BUFFER_NAME: + description: Monitor interface upstream buffer name + value: '"btmonitor"' + BLE_MONITOR_RTT_BUFFER_SIZE: + description: Monitor interface upstream buffer size + value: 256 + BLE_MONITOR_RTT_BUFFERED: + description: > + Enables buffering when using monitor interface over RTT. The data + are written to RTT once complete packet is created in intermediate + buffer. This allows to skip complete packet if there is not enough + space in RTT buffer (e.g. there is no reader connected). If disabled, + monitor will simply block waiting for RTT to free space in buffer. + value: 1 + BLE_MONITOR_CONSOLE_BUFFER_SIZE: + description: > + Size of internal buffer for console output. Any line exceeding this + length value will be split. + value: 128 + + # L2CAP settings. + BLE_L2CAP_MAX_CHANS: + description: > + The number of L2CAP channels to allocate. The default value allows + for the signal, ATT, and SM channels for each connection. + value: '3*MYNEWT_VAL_BLE_MAX_CONNECTIONS' + BLE_L2CAP_SIG_MAX_PROCS: + description: > + The maximum number of concurrent L2CAP signal procedures. + value: 1 + BLE_L2CAP_JOIN_RX_FRAGS: + description: > + Whether to collapse incoming L2CAP fragments into a minimal set of + mbufs. + 1: Slower, more memory efficient. + 0: Faster, less memory efficient. + value: 1 + BLE_L2CAP_RX_FRAG_TIMEOUT: + description: > + Expiry time for incoming data packets (ms). If this much time + passes since the previous fragment was received, the connection is + terminated. A value of 0 means no timeout. + value: 30000 + BLE_L2CAP_COC_MAX_NUM: + description: > + Defines maximum number of LE Connection Oriented Channels channels. + When set to (0), LE COC is not compiled in. + value: 0 + BLE_L2CAP_COC_MPS: + description: > + Defines the MPS of L2CAP COC module. This is actually NimBLE's internal + L2CAP MTU. The default MPS size is chosen in a way, that the MPS plus + the required HCI and L2CAP headers fit into the smallest available + MSYS blocks. + value: 'MYNEWT_VAL_MSYS_1_BLOCK_SIZE-8' + + BLE_L2CAP_ENHANCED_COC: + description: > + Enables LE Enhanced CoC mode. + value: 0 + restrictions: + - '(BLE_L2CAP_COC_MAX_NUM > 0) && (BLE_VERSION >= 52) if 1' + + # Security manager settings. + BLE_SM_LEGACY: + description: 'Security manager legacy pairing.' + value: 1 + BLE_SM_SC: + description: 'Security manager secure connections (4.2).' + value: 0 + + BLE_SM_MAX_PROCS: + description: > + The maximum number of concurrent security manager procedures. + value: 1 + BLE_SM_IO_CAP: + description: > + The IO capabilities to report during pairing. Valid values are: + BLE_HS_IO_DISPLAY_ONLY + BLE_HS_IO_DISPLAY_YESNO + BLE_HS_IO_KEYBOARD_ONLY + BLE_HS_IO_NO_INPUT_OUTPUT + BLE_HS_IO_KEYBOARD_DISPLAY + value: 'BLE_HS_IO_NO_INPUT_OUTPUT' + BLE_SM_OOB_DATA_FLAG: + description: > + Whether the out-of-band pairing algorithm is advertised. (0/1) + value: 0 + BLE_SM_BONDING: + description: > + Enables bonding (persistence and restoration of secure links). (0/1) + value: 0 + BLE_SM_MITM: + description: > + Whether man-in-the-middle protection is advertised during + pairing. (0/1) + value: 0 + BLE_SM_KEYPRESS: + description: > + Whether keypress support is advertised during pairing. (0/1) + value: 0 + BLE_SM_OUR_KEY_DIST: + description: > + A bitmap indicating which keys to distribute during pairing. The + bits are defined as follows: + 0x01: BLE_SM_PAIR_KEY_DIST_ENC + 0x02: BLE_SM_PAIR_KEY_DIST_ID + 0x04: BLE_SM_PAIR_KEY_DIST_SIGN + 0x08: BLE_SM_PAIR_KEY_DIST_LINK + value: 0 + BLE_SM_THEIR_KEY_DIST: + description: > + A bitmap indicating which keys to accept during pairing. The + bits are defined as follows: + 0x01: BLE_SM_PAIR_KEY_DIST_ENC + 0x02: BLE_SM_PAIR_KEY_DIST_ID + 0x04: BLE_SM_PAIR_KEY_DIST_SIGN + 0x08: BLE_SM_PAIR_KEY_DIST_LINK + value: 0 + BLE_SM_SC_DEBUG_KEYS: + description: > + Enable SM debug mode. In this mode SM uses predefined DH key pair as + described in Core Specification 5.0, Vol. 3, Part H, 2.3.5.6.1. This + allows to decrypt air traffic easily and thus should be only used + for debugging. + value: 0 + + # GAP options. + BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE: + description: > + Controls the number of connection parameter updates that can be pending + simultaneously. Devices with many concurrent connections may need + to increase this value. + value: 1 + + # Supported GATT procedures. By default: + # o Notify and indicate are enabled; + # o All other procedures are enabled for centrals. + BLE_GATT_DISC_ALL_SVCS: + description: > + Enables the Discover All Primary Services GATT procedure. (0/1) + value: MYNEWT_VAL_BLE_ROLE_CENTRAL + BLE_GATT_DISC_SVC_UUID: + description: > + Enables the Discover Primary Services by Service UUID GATT + procedure. (0/1) + value: MYNEWT_VAL_BLE_ROLE_CENTRAL + BLE_GATT_FIND_INC_SVCS: + description: > + Enables the Find Included Services GATT procedure. (0/1) + value: MYNEWT_VAL_BLE_ROLE_CENTRAL + BLE_GATT_DISC_ALL_CHRS: + description: > + Enables the Discover All Characteristics of a Service GATT + procedure. (0/1) + value: MYNEWT_VAL_BLE_ROLE_CENTRAL + BLE_GATT_DISC_CHR_UUID: + description: > + Enables the Discover Characteristics by UUID GATT procedure. (0/1) + value: MYNEWT_VAL_BLE_ROLE_CENTRAL + BLE_GATT_DISC_ALL_DSCS: + description: > + Enables the Discover All Primary Services GATT procedure. (0/1) + value: MYNEWT_VAL_BLE_ROLE_CENTRAL + BLE_GATT_READ: + description: > + Enables the Read Characteristic Value GATT procedure. (0/1) + (0/1) + value: MYNEWT_VAL_BLE_ROLE_CENTRAL + BLE_GATT_READ_UUID: + description: > + Enables the Read Using Characteristic UUID GATT procedure. (0/1) + value: MYNEWT_VAL_BLE_ROLE_CENTRAL + BLE_GATT_READ_LONG: + description: > + Enables the Read Long Characteristic Values GATT procedure. (0/1) + value: MYNEWT_VAL_BLE_ROLE_CENTRAL + BLE_GATT_READ_MULT: + description: > + Enables the Read Multiple Characteristic Values GATT procedure. + (0/1) + value: MYNEWT_VAL_BLE_ROLE_CENTRAL + BLE_GATT_WRITE_NO_RSP: + description: > + Enables the Write Without Response GATT procedure. (0/1) + value: MYNEWT_VAL_BLE_ROLE_CENTRAL + BLE_GATT_SIGNED_WRITE: + description: > + Enables the Signed Write Without Response GATT procedure. (0/1) + value: MYNEWT_VAL_BLE_ROLE_CENTRAL + BLE_GATT_WRITE: + description: > + Enables the Write Characteristic Value GATT procedure. (0/1) + value: MYNEWT_VAL_BLE_ROLE_CENTRAL + BLE_GATT_WRITE_LONG: + description: > + Enables the Write Long Characteristic Values GATT procedure. (0/1) + value: MYNEWT_VAL_BLE_ROLE_CENTRAL + BLE_GATT_WRITE_RELIABLE: + description: > + Enables the Reliable Writes GATT procedure. (0/1) + value: MYNEWT_VAL_BLE_ROLE_CENTRAL + BLE_GATT_NOTIFY: + description: > + Enables sending and receiving of GATT notifications. (0/1) + value: 1 + BLE_GATT_INDICATE: + description: > + Enables sending and receiving of GATT indications. (0/1) + value: 1 + + # GATT options. + BLE_GATT_READ_MAX_ATTRS: + description: > + The maximum number of attributes that can be read with a single + GATT Read Multiple Characteristic Values procedure. (0/1) + value: 8 + BLE_GATT_WRITE_MAX_ATTRS: + description: > + The maximum number of attributes that can be written with a single + GATT Reliable Write procedure. (0/1) + value: 4 + BLE_GATT_MAX_PROCS: + description: > + The maximum number of concurrent client GATT procedures. (0/1) + value: 4 + BLE_GATT_RESUME_RATE: + description: > + The rate to periodically resume GATT procedures that have stalled + due to memory exhaustion. (0/1) Units are milliseconds. (0/1) + value: 1000 + + # Supported server ATT commands. (0/1) + BLE_ATT_SVR_FIND_INFO: + description: > + Enables processing of incoming Find Information Request ATT + commands. (0/1) + value: 1 + BLE_ATT_SVR_FIND_TYPE: + description: > + Enables processing of incoming Find By Type Value Request ATT + commands. (0/1) + value: 1 + BLE_ATT_SVR_READ_TYPE: + description: > + Enables processing of incoming Read By Type Request ATT commands. + (0/1) + value: 1 + BLE_ATT_SVR_READ: + description: > + Enables processing of incoming Read Request ATT commands. (0/1) + value: 1 + BLE_ATT_SVR_READ_BLOB: + description: > + Enables processing of incoming Read Blob Request ATT commands. + (0/1) + value: 1 + BLE_ATT_SVR_READ_MULT: + description: > + Enables processing of incoming Read Multiple Request ATT commands. + (0/1) + value: 1 + BLE_ATT_SVR_READ_GROUP_TYPE: + description: > + Enables processing of incoming Read by Group Type Request ATT + commands. (0/1) + value: 1 + BLE_ATT_SVR_WRITE: + description: > + Enables processing of incoming Write Request ATT commands. (0/1) + value: 1 + BLE_ATT_SVR_WRITE_NO_RSP: + description: > + Enables processing of incoming Write Command ATT commands. (0/1) + value: 1 + BLE_ATT_SVR_SIGNED_WRITE: + description: > + Enables processing of incoming Signed Write Command ATT commands. + (0/1) + value: 1 + BLE_ATT_SVR_QUEUED_WRITE: + description: > + Enables processing of incoming Prepare Write Request and Execute + Write Request ATT commands. (0/1) + value: 1 + BLE_ATT_SVR_NOTIFY: + description: > + Enables processing of incoming Handle Value Notification ATT + commands. (0/1) + value: 1 + BLE_ATT_SVR_INDICATE: + description: > + Enables processing of incoming Handle Value Indication ATT + commands. (0/1) + value: 1 + + # ATT options. + BLE_ATT_PREFERRED_MTU: + description: The preferred MTU to indicate in MTU exchange commands. + value: 256 + + BLE_ATT_SVR_MAX_PREP_ENTRIES: + description: > + A GATT server uses these when a peer performs a "write long + characteristic values" or "write long characteristic descriptors" + procedure. One of these resources is consumed each time a peer + sends a partial write. + value: 64 + + BLE_ATT_SVR_QUEUED_WRITE_TMO: + description: > + Expiry time for incoming ATT queued writes (ms). If this much + time passes since the previous prepared write was received, the + connection is terminated. A value of 0 means no timeout. + value: 30000 + + # Privacy options. + BLE_RPA_TIMEOUT: + description: > + The rate that new random addresses should be generated (seconds). + value: 300 + + # Store settings. + BLE_STORE_MAX_BONDS: + description: > + Maximum number of bonds that can be persisted. Note: increasing + this value may also require increasing the capacity of the + underlying storage mechanism. + value: 3 + BLE_STORE_MAX_CCCDS: + description: > + Maximum number of client characteristic configuration descriptors + that can be persisted. Note: increasing this value may also + require increasing the capacity of the underlying storage + mechanism. + + value: 8 + + BLE_MESH: + description: > + This option enables Bluetooth Mesh support. The specific + features that are available may depend on other features + that have been enabled in the stack, such as GATT support. + value: 0 + + # Flow control settings. + BLE_HS_FLOW_CTRL: + description: > + Whether to enable host-side flow control. This should only be + enabled in host-only setups (i.e., not combined-host-controller). + value: 0 + + BLE_HS_FLOW_CTRL_ITVL: + description: > + The interval, in milliseconds, that the host should provide + number-of-completed-packets updates to the controller. + value: 1000 + + BLE_HS_FLOW_CTRL_THRESH: + description: > + If the number of data buffers available to the controller falls to + this number, immediately send a number-of-completed-packets event. + The free buffer count is calculated as follows: + (total-acl-bufs - bufs-freed-since-last-num-completed-event). + value: 2 + + BLE_HS_FLOW_CTRL_TX_ON_DISCONNECT: + description: > + If enabled, the host will immediately transmit a + host-number-of-completed-packets command whenever a connection + terminates. This behavior is not required by the standard, but is + a necessary workaround when interfacing with some controllers. + value: 0 + + BLE_HS_STOP_ON_SHUTDOWN: + description: > + Stops the Bluetooth host when the system shuts down. Stopping + entails aborting all GAP procedures and terminating open + connections. + value: 1 + + BLE_HS_STOP_ON_SHUTDOWN_TIMEOUT: + description: > + Timeout used in NimBLE's host stop procedure in ms. + value: 2000 + + BLE_HS_SYSINIT_STAGE: + description: > + Sysinit stage for the NimBLE host. + value: 200 + + ### Log settings. + + BLE_HS_LOG_MOD: + description: 'Numeric module ID to use for BLE host log messages.' + value: 4 + BLE_HS_LOG_LVL: + description: 'Minimum level for the BLE host log.' + value: 1 + +syscfg.logs: + BLE_HS_LOG: + module: MYNEWT_VAL(BLE_HS_LOG_MOD) + level: MYNEWT_VAL(BLE_HS_LOG_LVL) + +syscfg.vals.BLE_MESH: + BLE_SM_SC: 1 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/tools/log2smtest.rb b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/tools/log2smtest.rb new file mode 100644 index 000000000..e253e69f0 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/tools/log2smtest.rb @@ -0,0 +1,1029 @@ +#!/usr/bin/env ruby + +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +### This script converts a bletiny log into a security manager unit test. The +### input log must contain the connection establishment and complete pairing +### procedure. +### +### Arguments: None +### Stdin: bletiny log file + +$PAIR_ALG_STRINGS = { + 0 => [ 'BLE_SM_PAIR_ALG_JW', 'just works', 'jw' ], + 1 => [ 'BLE_SM_PAIR_ALG_PASSKEY', 'passkey entry', 'pk' ], + 2 => [ 'BLE_SM_PAIR_ALG_OOB', 'out of band', 'ob' ], + 3 => [ 'BLE_SM_PAIR_ALG_NUMCMP', 'numeric comparison', 'nc' ] +} + +$ADDR_TYPE_STRINGS = { + 0 => 'BLE_ADDR_TYPE_PUBLIC', + 1 => 'BLE_ADDR_TYPE_RANDOM', + 2 => 'BLE_ADDR_TYPE_RPA_PUB_DEFAULT', + 3 => 'BLE_ADDR_TYPE_RPA_RND_DEFAULT', +} + +$ACTION_STRINGS = { + 0 => 'BLE_SM_IOACT_NONE', + 1 => 'BLE_SM_IOACT_OOB', + 2 => 'BLE_SM_IOACT_INPUT', + 3 => 'BLE_SM_IOACT_DISP', + 4 => 'BLE_SM_IOACT_NUMCMP', +} + +$prev_idx = 0 +$ctxt = {} + +def test_case_name + type_str = $ctxt[:sc] ? "sc" : "lgcy" + init_str = $ctxt[:we_are_init] ? "us" : "peer" + alg_str = $PAIR_ALG_STRINGS[$ctxt[:pair_alg]][2] + iio_cap_str = "iio#{$ctxt[:pair_req][:io_cap]}" + rio_cap_str = "rio#{$ctxt[:pair_rsp][:io_cap]}" + bonding_str = "b#{$ctxt[:bonding] ? 1 : 0}" + iat_str = "iat#{$ctxt[:addrs][:init_type]}" + rat_str = "rat#{$ctxt[:addrs][:resp_type]}" + ikey_str = "ik#{$ctxt[:pair_rsp][:init_key_dist]}" + rkey_str = "rk#{$ctxt[:pair_rsp][:resp_key_dist]}" + + "ble_sm_" + + "#{type_str}_#{init_str}_#{alg_str}_#{iio_cap_str}_#{rio_cap_str}_" + + "#{bonding_str}_#{iat_str}_#{rat_str}_#{ikey_str}_#{rkey_str}" +end + +def test_case_comment +<<-eos +/** + * #{$ctxt[:sc] ? 'Secure connections' : 'Legacy'} pairing + * Master: #{$ctxt[:we_are_init] ? "us" : "peer"} + * Pair algorithm: #{$PAIR_ALG_STRINGS[$ctxt[:pair_alg]][1]} + * Initiator IO capabilities: #{$ctxt[:pair_req][:io_cap]} + * Responder IO capabilities: #{$ctxt[:pair_rsp][:io_cap]} + * Bonding: #{$ctxt[:bonding]} + * Initiator address type: #{$ADDR_TYPE_STRINGS[$ctxt[:addrs][:init_type]]} + * Responder address type: #{$ADDR_TYPE_STRINGS[$ctxt[:addrs][:resp_type]]} + * Initiator key distribution: #{$ctxt[:pair_rsp][:init_key_dist]} + * Responder key distribution: #{$ctxt[:pair_rsp][:resp_key_dist]} + */ +eos +end + +def to_hex_s(byte) + if byte.is_a?(String) + byte = s_to_i(byte) + end + + "0x#{byte.to_s(16).rjust(2, '0')}" +end + +# to_i(0) but interpret leading zeros as decimal. +def s_to_i(s) + if s[0..1] == "0x" + return s.to_i(16) + else + return s.to_i(10) + end +end + +def invalid_byte_line(msg, line) + str = "invalid byte line" + if msg != nil + str += ": #{msg}" + end + + str += "; line=#{line}" + + raise str +end + +def token_string_to_bytes(line, delim = ' ') + tokens = line.split(delim) + bytes = [] + tokens.each do |token| + begin + byte = token.to_i(16) + bytes << byte + rescue + invalid_byte_line("token=#{token}", line) + end + end + + return bytes +end + +def txrx_prefix(is_tx) + if is_tx + return "tx" + else + return "rx" + end +end + +def reqrsp_s(is_req) + reqrsp = nil + if is_req + return "req" + else + return "rsp" + end +end + +def bytes_to_arr_body(bytes, indent) + lines = [] + + idx = 0 + while idx < bytes.size + slice_len = nil + if bytes.size - idx >= 8 + slice_len = 8 + else + slice_len = bytes.size - idx + end + + slice = bytes[idx...(idx + slice_len)] + line = ' ' * indent + + slice.map{|b| to_hex_s(b)}.join(", ") + "," + lines << line + + idx += slice_len + end + + return lines.join("\n") << "\n" +end + +def bytes_to_arr(bytes, name, indent) + str = "#{' ' * indent}.#{name} = {\n" + str << bytes_to_arr_body(bytes, indent + 4) + str << "#{' ' * indent}}," + + return str +end + +def addr_string_to_bytes(addr_string) + token_string_to_bytes(addr_string, ':').reverse +end + +def parse_pair_cmd(line, is_req) + suffix = reqrsp_s(is_req) + re = %r{ + pair\s#{suffix}; + \s + conn=\d+ + \s + io_cap=(?\d+) + \s + oob_data_flag=(?\d+) + \s + authreq=(?0x[0-9a-f]+) + \s + mac_enc_key_size=(?\d+) + \s + init_key_dist=(?\d+) + \s + resp_key_dist=(?\d+) + }x + + m = re.match(line) + if m == nil + return nil + end + + cmd = {} + cmd[:io_cap] = s_to_i(m[:io_cap]) + cmd[:oob_data_flag] = s_to_i(m[:oob_data_flag]) + cmd[:authreq] = s_to_i(m[:authreq]) + cmd[:max_enc_key_size] = s_to_i(m[:max_enc_key_size]) + cmd[:init_key_dist] = s_to_i(m[:init_key_dist]) + cmd[:resp_key_dist] = s_to_i(m[:resp_key_dist]) + + return cmd +end + +def parse_privkey(line) + if !(line =~ /our privkey=(.+)/) + return nil + end + return token_string_to_bytes($1) +end + +def parse_public_key(line, is_tx) + prefix = txrx_prefix(is_tx) + if !(line =~ /#{prefix}ed sm command: public key; conn=\d+ x=(.+) y=(.+)/) + return nil + end + + pubkey = {} + pubkey[:x] = token_string_to_bytes($1) + pubkey[:y] = token_string_to_bytes($2) + + if pubkey[:x].size != 32 + raise "invalid public key: x length incorrect; line=#{line}" + end + + if pubkey[:y].size != 32 + raise "invalid public key: y length incorrect; line=#{line}" + end + + return pubkey +end + +def parse_confirm(line, is_tx) + prefix = txrx_prefix(is_tx) + if !(line =~ /#{prefix}ed sm command: confirm; conn=\d+ value=(.+)/) + return nil + end + + bytes = token_string_to_bytes($1) + if bytes.size != 16 + raise "invalid confirm line (length mismatch): #{line}" + end + + return { :value => bytes } +end + +def parse_random(line, is_tx) + prefix = txrx_prefix(is_tx) + if !(line =~ /#{prefix}ed sm command: random; conn=\d+ value=(.+)/) + return nil + end + + bytes = token_string_to_bytes($1) + if bytes.size != 16 + raise "invalid random line (length mismatch): #{line}" + end + + return { :value => bytes } +end + +def parse_stk(line) + if !(line =~ /^ out=(.+)/) + return nil + end + + bytes = token_string_to_bytes($1) + if bytes.size != 16 + raise "invalid stk line (length mismatch): #{line}" + end + + return bytes +end + +def parse_dhkey_check(line, is_tx) + prefix = txrx_prefix(is_tx) + if !(line =~ /#{prefix}ed sm command: dhkey check; conn=\d+ value=(.+)/) + return nil + end + + bytes = token_string_to_bytes($1) + if bytes.size != 16 + raise "invalid dhkey_check line (length mismatch): #{line}" + end + + return { :value => bytes } +end + +def parse_ltk(line) + if !(line =~ /persisting.+ltk=([^ ]+)/) + return nil + end + + bytes = $1.split(":") + if bytes.size != 16 + raise "invalid ltk line (length mismatch): exp=16 got=#{bytes.size} " + + "line=#{line}" + end + + return bytes +end + +def parse_enc_info(line, is_tx) + prefix = txrx_prefix(is_tx) + if !(line =~ /#{prefix}ed sm command: enc info; conn=\d+ ltk=(.+)/) + return nil + end + + bytes = token_string_to_bytes($1) + if bytes.size != 16 + raise "invalid enc info line (length mismatch): #{line}" + end + + return { :ltk => bytes } +end + +def parse_master_id(line, is_tx) + prefix = txrx_prefix(is_tx) + if !(line =~ /#{prefix}ed sm command: master id; conn=\d+ ediv=(.+) rand=(.+)/) + return nil + end + + return { + :ediv => s_to_i($1), + :rand => s_to_i($2), + } +end + +def parse_id_info(line, is_tx) + prefix = txrx_prefix(is_tx) + if !(line =~ /#{prefix}ed sm command: id info; conn=\d+ irk=(.+)/) + return nil + end + + bytes = token_string_to_bytes($1) + if bytes.size != 16 + raise "invalid id info line (length mismatch): #{line}" + end + + return { :irk => bytes } +end + +def parse_id_addr_info(line, is_tx) + prefix = txrx_prefix(is_tx) + if !(line =~ /#{prefix}ed sm command: id addr info; conn=\d+ addr_type=(\d+) addr=(.+)/) + return nil + end + + bytes = addr_string_to_bytes($2) + if bytes.size != 6 + raise "invalid id addr info line (length mismatch): #{line}" + end + + return { + :addr_type => s_to_i($1), + :addr => bytes, + } +end + +def parse_sign_info(line, is_tx) + prefix = txrx_prefix(is_tx) + if !(line =~ /#{prefix}ed sm command: sign info; conn=\d+ sig_key=(.+)/) + return nil + end + + bytes = token_string_to_bytes($1) + if bytes.size != 16 + raise "invalid sign info line (length mismatch): #{line}" + end + + return { + :sig_key => bytes, + } +end + +def parse_passkey_info(line) + passkey_info = {} + + case line + when /passkey action event; action=4 numcmp=(\d+)/ + passkey_info[:action] = 4 + passkey_info[:numcmp] = $1.to_i(10) + when /^b passkey conn=\d+ action=1 oob=(\S+)/ + passkey_info[:action] = 1 + passkey_info[:oob] = token_string_to_bytes($1, ':') + when /^b passkey conn=\d+ action=2 key=(\d+)/ + passkey_info[:action] = 2 + passkey_info[:key] = $1.to_i(10) + when /b passkey conn=\d+ action=3 key=(\d+)/ + passkey_info[:action] = 3 + passkey_info[:key] = $1.to_i(10) + else + return nil + end + + return passkey_info +end + +def parse_addrs(line) + if !(line =~ /our_ota_addr_type=(\d+) our_ota_addr=(\S+) our_id_addr_type=(\d+) our_id_addr=(\S+) peer_ota_addr_type=(\d+) peer_ota_addr=(\S+) peer_id_addr_type=(\d+) peer_id_addr=(\S+)/) + return nil + end + + our_ota_addr_bytes = addr_string_to_bytes($2) + our_id_addr_bytes = addr_string_to_bytes($4) + peer_ota_addr_bytes = addr_string_to_bytes($6) + peer_id_addr_bytes = addr_string_to_bytes($8) + + if $ctxt[:we_are_init] + init_id_bytes = our_id_addr_bytes + init_ota_bytes = our_ota_addr_bytes + resp_id_bytes = peer_id_addr_bytes + resp_ota_bytes = peer_ota_addr_bytes + init_addr_type = s_to_i($1) + resp_addr_type = s_to_i($5) + else + init_id_bytes = peer_id_addr_bytes + init_ota_bytes = peer_ota_addr_bytes + resp_id_bytes = our_id_addr_bytes + resp_ota_bytes = our_ota_addr_bytes + init_addr_type = s_to_i($5) + resp_addr_type = s_to_i($1) + end + + if init_id_bytes == init_ota_bytes + init_ota_bytes = [0] * 6 + end + if resp_id_bytes == resp_ota_bytes + resp_ota_bytes = [0] * 6 + end + + return { + :init_type => init_addr_type, + :resp_type => resp_addr_type, + :init_id_addr => init_id_bytes, + :resp_id_addr => resp_id_bytes, + :init_rpa => init_ota_bytes, + :resp_rpa => resp_ota_bytes, + } +end + +def detect_initiator(lines) + lines.each do |line| + if line =~ /txed sm command: pair req/ + $ctxt[:we_are_init] = true + elsif line =~ /txed sm command: pair rsp/ + $ctxt[:we_are_init] = false + end + end + + if $ctxt[:we_are_init] == nil + raise "could not detect which peer is the initiator" + end +end + +def pair_cmd_to_s(cmd, is_req) + suffix = reqrsp_s(is_req) + return <<-eos + .pair_#{suffix} = { + .io_cap = #{to_hex_s(cmd[:io_cap])}, + .oob_data_flag = #{to_hex_s(cmd[:oob_data_flag])}, + .authreq = #{to_hex_s(cmd[:authreq])}, + .max_enc_key_size = #{to_hex_s(cmd[:max_enc_key_size])}, + .init_key_dist = #{to_hex_s(cmd[:init_key_dist])}, + .resp_key_dist = #{to_hex_s(cmd[:resp_key_dist])}, + }, + eos +end + +def privkey_to_s(privkey) + return bytes_to_arr(privkey, "our_priv_key", 8) +end + +def public_key_to_s(public_key, is_req) + suffix = reqrsp_s(is_req) + return <<-eos + .public_key_#{suffix} = { +#{bytes_to_arr(public_key[:x], "x", 12)} +#{bytes_to_arr(public_key[:y], "y", 12)} + }, + eos +end + +def confirm_to_s(confirm, is_req, idx) + return <<-eos + .confirm_#{reqrsp_s(is_req)}[#{idx}] = { +#{bytes_to_arr(confirm[:value], "value", 12)} + }, + eos +end + +def random_to_s(random, is_req, idx) + return <<-eos + .random_#{reqrsp_s(is_req)}[#{idx}] = { +#{bytes_to_arr(random[:value], "value", 12)} + }, + eos +end + +def ltk_to_s(ltk) + return bytes_to_arr(ltk, "ltk", 8) +end + +def stk_to_s(stk) + return bytes_to_arr(stk, "stk", 8) +end + +def enc_info_to_s(id_info, is_req) + return <<-eos + .enc_info_#{reqrsp_s(is_req)} = { +#{bytes_to_arr(id_info[:ltk], "ltk", 12)} + }, + eos +end + +def master_id_to_s(master_id, is_req) + return <<-eos + .master_id_#{reqrsp_s(is_req)} = { + .ediv = 0x#{master_id[:ediv].to_s(16)}, + .rand_val = 0x#{master_id[:rand].to_s(16)}, + }, + eos +end + +def id_info_to_s(id_info, is_req) + return <<-eos + .id_info_#{reqrsp_s(is_req)} = { +#{bytes_to_arr(id_info[:irk], "irk", 12)} + }, + eos +end + +def id_addr_info_to_s(id_addr_info, is_req) + return <<-eos + .id_addr_info_#{reqrsp_s(is_req)} = { + .addr_type = #{id_addr_info[:addr_type]}, +#{bytes_to_arr(id_addr_info[:addr], "bd_addr", 12)} + }, + eos +end + +def sign_info_to_s(sign_info, is_req) + return <<-eos + .sign_info_#{reqrsp_s(is_req)} = { +#{bytes_to_arr(sign_info[:sig_key], "sig_key", 12)} + }, + eos +end + +def passkey_info_fill(passkey_info) + case passkey_info[:action] + # None + when 0 + $ctxt[:pair_alg] = 0 + $ctxt[:authenticated] = false + + # OOB + when 1 + $ctxt[:pair_alg] = 2 + $ctxt[:authenticated] = true + + # Input + when 2 + $ctxt[:pair_alg] = 1 + $ctxt[:authenticated] = true + + # Display + when 3 + $ctxt[:pair_alg] = 1 + $ctxt[:authenticated] = true + + # Numeric comparison + when 4 + $ctxt[:pair_alg] = 3 + $ctxt[:authenticated] = true + + else + raise "invalid MITM action: #{passkey_info[:action]}" + end +end + +def passkey_info_s + passkey_info = $ctxt[:passkey_info] + action_str = $ACTION_STRINGS[passkey_info[:action]] + + result = <<-eos + .pair_alg = #{$ctxt[:pair_alg]}, + .authenticated = #{$ctxt[:authenticated]}, + .passkey_info = { + .passkey = { + .action = #{action_str}, + eos + + if passkey_info[:key] != nil + result << <<-eos + .passkey = #{passkey_info[:key].to_i}, + eos + end + if passkey_info[:oob] != nil + result << <<-eos +#{bytes_to_arr(passkey_info[:oob], "oob", 16)} + eos + end + if passkey_info[:numcmp] != nil + result << <<-eos + .numcmp_accept = 1, + eos + end + + result << <<-eos + }, + eos + + if passkey_info[:numcmp] != nil + result << <<-eos + .exp_numcmp = #{passkey_info[:numcmp].to_i}, + eos + end + + result << <<-eos + }, + eos +end + +def addrs_to_s(addrs) + s = '' + + init_type = addrs[:init_type] + resp_type = addrs[:resp_type] + + if init_type != 0 + s += " .init_addr_type = #{$ADDR_TYPE_STRINGS[init_type]},\n" + end + s += bytes_to_arr(addrs[:init_id_addr], "init_id_addr", 8) + "\n" + if init_type >= 2 + s += bytes_to_arr(addrs[:init_rpa], "init_rpa", 8) + "\n" + end + + if resp_type != 0 + s += " .resp_addr_type = #{$ADDR_TYPE_STRINGS[resp_type]},\n" + end + s += bytes_to_arr(addrs[:resp_id_addr], "resp_id_addr", 8) + "\n" + if resp_type >= 2 + s += bytes_to_arr(addrs[:resp_rpa], "resp_rpa", 8) + "\n" + end + + return s +end + +def dhkey_check_to_s(dhkey_check, is_req) + return <<-eos + .dhkey_check_#{reqrsp_s(is_req)} = { +#{bytes_to_arr(dhkey_check[:value], "value", 12)} + }, + eos +end + +def extract_one(lines, ignore_prev = false) + if ignore_prev + start = 0 + else + start = $prev_idx + end + + (start...lines.size).each do |idx| + line = lines[idx] + result = yield(line) + if result != nil + if !ignore_prev + $prev_idx = idx + end + return result + end + end + + return nil +end + +def extract_pair_req(lines) + return extract_one(lines) {|line| parse_pair_cmd(line, true)} +end + +def extract_pair_rsp(lines) + return extract_one(lines) {|line| parse_pair_cmd(line, false)} +end + +def extract_privkey(lines) + return extract_one(lines) {|line| parse_privkey(line)} +end + +def extract_public_key_req(lines) + return extract_one(lines) do |line| + parse_public_key(line, $ctxt[:we_are_init]) + end +end + +def extract_public_key_rsp(lines) + return extract_one(lines) do |line| + parse_public_key(line, !$ctxt[:we_are_init]) + end +end + +def extract_confirm_req(lines) + return extract_one(lines) do |line| + parse_confirm(line, $ctxt[:we_are_init]) + end +end + +def extract_confirm_rsp(lines) + return extract_one(lines) do |line| + parse_confirm(line, !$ctxt[:we_are_init]) + end +end + +def extract_random_req(lines) + return extract_one(lines) do |line| + parse_random(line, $ctxt[:we_are_init]) + end +end + +def extract_random_rsp(lines) + return extract_one(lines) do |line| + parse_random(line, !$ctxt[:we_are_init]) + end +end + +def extract_confirm_random(lines) + confirm_reqs = [] + confirm_rsps = [] + random_reqs = [] + random_rsps = [] + + idx = 0 + loop do + confirm_req = extract_confirm_req(lines) + if confirm_req != nil + confirm_reqs << confirm_req + end + + confirm_rsp = extract_confirm_rsp(lines) + break if confirm_rsp == nil + if idx >= 20 + raise "too many confirm rsps (>20)" + end + confirm_rsps << confirm_rsp + + random_req = extract_random_req(lines) + break if random_req == nil + random_reqs << random_req + + random_rsp = extract_random_rsp(lines) + break if random_rsp == nil + random_rsps << random_rsp + + idx += 1 + end + + return confirm_reqs, confirm_rsps, random_reqs, random_rsps +end + +def extract_stk(lines) + return extract_one(lines, true) do |line| + parse_stk(line) + end +end + +def extract_dhkey_check_req(lines) + return extract_one(lines) do |line| + parse_dhkey_check(line, $ctxt[:we_are_init]) + end +end + +def extract_dhkey_check_rsp(lines) + return extract_one(lines) do |line| + parse_dhkey_check(line, !$ctxt[:we_are_init]) + end +end + +def extract_enc_info_req(lines) + return extract_one(lines) do |line| + parse_enc_info(line, !$ctxt[:we_are_init]) + end +end + +def extract_enc_info_rsp(lines) + return extract_one(lines) do |line| + parse_enc_info(line, $ctxt[:we_are_init]) + end +end + +def extract_master_id_req(lines) + return extract_one(lines) do |line| + parse_master_id(line, !$ctxt[:we_are_init]) + end +end + +def extract_master_id_rsp(lines) + return extract_one(lines) do |line| + parse_master_id(line, $ctxt[:we_are_init]) + end +end + +def extract_id_info_req(lines) + return extract_one(lines) do |line| + parse_id_info(line, !$ctxt[:we_are_init]) + end +end + +def extract_id_info_rsp(lines) + return extract_one(lines) do |line| + parse_id_info(line, $ctxt[:we_are_init]) + end +end + +def extract_id_addr_info_req(lines) + return extract_one(lines) do |line| + parse_id_addr_info(line, !$ctxt[:we_are_init]) + end +end + +def extract_id_addr_info_rsp(lines) + return extract_one(lines) do |line| + parse_id_addr_info(line, $ctxt[:we_are_init]) + end +end + +def extract_sign_info_req(lines) + return extract_one(lines) do |line| + parse_sign_info(line, !$ctxt[:we_are_init]) + end +end + +def extract_sign_info_rsp(lines) + return extract_one(lines) do |line| + parse_sign_info(line, $ctxt[:we_are_init]) + end +end + +def extract_ltk(lines) + return extract_one(lines) do |line| + parse_ltk(line) + end +end + +def extract_passkey_info(lines) + passkey_info = extract_one(lines, true) do |line| + parse_passkey_info(line) + end + + if passkey_info == nil + passkey_info = { :action => 0 } + end + + return passkey_info +end + +def extract_addrs(lines) + return extract_one(lines) do |line| + parse_addrs(line) + end +end + + +lines = STDIN.readlines + +detect_initiator(lines) +$ctxt[:pair_req] = extract_pair_req(lines) +$ctxt[:pair_rsp] = extract_pair_rsp(lines) +$ctxt[:privkey] = extract_privkey(lines) +$ctxt[:public_key_req] = extract_public_key_req(lines) +$ctxt[:public_key_rsp] = extract_public_key_rsp(lines) +$ctxt[:confirm_reqs], $ctxt[:confirm_rsps], $ctxt[:random_reqs], $ctxt[:random_rsps] = extract_confirm_random(lines) +$ctxt[:passkey_info] = extract_passkey_info(lines) +$ctxt[:dhkey_check_req] = extract_dhkey_check_req(lines) +$ctxt[:dhkey_check_rsp] = extract_dhkey_check_rsp(lines) +$ctxt[:enc_info_req] = extract_enc_info_req(lines) +$ctxt[:master_id_req] = extract_master_id_req(lines) +$ctxt[:id_info_req] = extract_id_info_req(lines) +$ctxt[:id_addr_info_req] = extract_id_addr_info_req(lines) +$ctxt[:sign_info_req] = extract_sign_info_req(lines) +$ctxt[:enc_info_rsp] = extract_enc_info_rsp(lines) +$ctxt[:master_id_rsp] = extract_master_id_rsp(lines) +$ctxt[:id_info_rsp] = extract_id_info_rsp(lines) +$ctxt[:id_addr_info_rsp] = extract_id_addr_info_rsp(lines) +$ctxt[:sign_info_rsp] = extract_sign_info_rsp(lines) +$ctxt[:addrs] = extract_addrs(lines) +$ctxt[:ltk] = extract_ltk(lines) +$ctxt[:stk] = extract_stk(lines) + +expected_confirm_rsps = nil +expected_random_reqs = nil +expected_random_rsps = nil +if $ctxt[:confirm_reqs].size == 0 + expected_confirm_rsps = 1 + expected_random_reqs = 1 + expected_random_rsps = 1 +else + expected_confirm_rsps = $ctxt[:confirm_reqs].size + expected_random_reqs = $ctxt[:random_reqs].size + expected_random_rsps = $ctxt[:random_rsps].size +end + +if $ctxt[:confirm_rsps].size != expected_confirm_rsps + raise "wrong number of confirm responses " + + "(exp=#{expected_confirm_rsps}; got=#{$ctxt[:confirm_rsps].size}" +end + +if $ctxt[:random_reqs].size != expected_random_reqs + raise "wrong number of random requests " + + "(exp=#{expected_random_reqs}; got=#{$ctxt[:random_reqs].size}" +end + +if $ctxt[:random_rsps].size != expected_random_rsps + raise "wrong number of random responses " + + "(exp=#{expected_random_rsps}; got=#{$ctxt[:random_rsps].size}" +end + +passkey_info_fill($ctxt[:passkey_info]) + +$ctxt[:sc] = $ctxt[:public_key_req] != nil +$ctxt[:bonding] = $ctxt[:pair_req][:authreq] & 1 == 1 && + $ctxt[:pair_rsp][:authreq] & 1 == 1 + +puts test_case_comment() +puts <<-eos +TEST_CASE(#{test_case_name()}) +{ + struct ble_sm_test_params params; + + params = (struct ble_sm_test_params) { +eos + +puts addrs_to_s($ctxt[:addrs]) + +puts pair_cmd_to_s($ctxt[:pair_req], true) +puts pair_cmd_to_s($ctxt[:pair_rsp], false) + +if $ctxt[:sc] + puts privkey_to_s($ctxt[:privkey]) + puts public_key_to_s($ctxt[:public_key_req], true) + puts public_key_to_s($ctxt[:public_key_req], false) +end + +$ctxt[:confirm_rsps].size.times do |i| + confirm_req = $ctxt[:confirm_reqs][i] + confirm_rsp = $ctxt[:confirm_rsps][i] + random_req = $ctxt[:random_reqs][i] + random_rsp = $ctxt[:random_rsps][i] + + if confirm_req != nil + puts confirm_to_s(confirm_req, true, i) + end + + puts confirm_to_s(confirm_rsp, false, i) + puts random_to_s(random_req, true, i) + puts random_to_s(random_rsp, false, i) +end + +if $ctxt[:sc] + puts dhkey_check_to_s($ctxt[:dhkey_check_req], true) + puts dhkey_check_to_s($ctxt[:dhkey_check_rsp], false) +end + +if $ctxt[:enc_info_req] != nil + puts enc_info_to_s($ctxt[:enc_info_req], true) +end +if $ctxt[:master_id_req] != nil + puts master_id_to_s($ctxt[:master_id_req], true) +end +if $ctxt[:id_info_req] != nil + puts id_info_to_s($ctxt[:id_info_req], true) +end +if $ctxt[:id_addr_info_req] != nil + puts id_addr_info_to_s($ctxt[:id_addr_info_req], true) +end +if $ctxt[:sign_info_req] != nil + puts sign_info_to_s($ctxt[:sign_info_req], true) +end +if $ctxt[:enc_info_rsp] != nil + puts enc_info_to_s($ctxt[:enc_info_rsp], false) +end +if $ctxt[:master_id_rsp] != nil + puts master_id_to_s($ctxt[:master_id_rsp], false) +end +if $ctxt[:id_info_rsp] != nil + puts id_info_to_s($ctxt[:id_info_rsp], false) +end +if $ctxt[:id_addr_info_rsp] != nil + puts id_addr_info_to_s($ctxt[:id_addr_info_rsp], false) +end +if $ctxt[:sign_info_rsp] != nil + puts sign_info_to_s($ctxt[:sign_info_rsp], false) +end +if $ctxt[:sc] + puts ltk_to_s($ctxt[:ltk]) +else + puts stk_to_s($ctxt[:stk]) +end +puts passkey_info_s() + +puts ' };' + +if $ctxt[:sc] + if $ctxt[:we_are_init] + puts ' ble_sm_test_util_us_sc_good(¶ms);' + else + puts ' ble_sm_test_util_peer_sc_good(¶ms);' + end +else + if $ctxt[:we_are_init] + puts ' ble_sm_test_util_us_lgcy_good(¶ms);' + else + puts ' ble_sm_test_util_peer_lgcy_good(¶ms);' + end +end +puts '}' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/host/util/util.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/include/host/util/util.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/host/util/util.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/include/host/util/util.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/pkg.yml new file mode 100644 index 000000000..0f5f3a5de --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/pkg.yml @@ -0,0 +1,29 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: nimble/host/util +pkg.description: Supplementary utilities for the NimBLE host +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - ble + - bluetooth + +pkg.deps: + - nimble/host diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/util/src/addr.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/src/addr.c similarity index 94% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/util/src/addr.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/src/addr.c index 9b43d237c..b8195a5b7 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/util/src/addr.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/src/addr.c @@ -17,11 +17,11 @@ * under the License. */ -#include "host/ble_hs.h" -#include "host/util/util.h" +#include "nimble/nimble/host/include/host/ble_hs.h" +#include "../include/host/util/util.h" #if MYNEWT_VAL(BLE_CONTROLLER) -#include "controller/ble_hw.h" +#include "nimble/nimble/controller/include/controller/ble_hw.h" #endif static int diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/syscfg.yml new file mode 100644 index 000000000..2cdd57468 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/syscfg.yml @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +syscfg.defs: diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ble.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/ble.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ble.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/ble.h index 3fc2902ec..f6847728c 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ble.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/ble.h @@ -22,8 +22,8 @@ #include #include -#include "syscfg/syscfg.h" -#include "os/os.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/os/os.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ble_hci_trans.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/ble_hci_trans.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/ble_hci_trans.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/ble_hci_trans.h index e8d3ec031..d4c353f1f 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/ble_hci_trans.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/ble_hci_trans.h @@ -21,7 +21,7 @@ #define H_HCI_TRANSPORT_ #include -#include "os/os_mempool.h" +#include "nimble/porting/nimble/include/os/os_mempool.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/hci_common.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/hci_common.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/hci_common.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/hci_common.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_npl.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/nimble_npl.h similarity index 97% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_npl.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/nimble_npl.h index 883832289..091cbea59 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_npl.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/nimble_npl.h @@ -23,7 +23,6 @@ #include #include #include -#include "nimconfig.h" #ifdef __cplusplus extern "C" { @@ -51,7 +50,7 @@ enum ble_npl_error { typedef enum ble_npl_error ble_npl_error_t; /* Include OS-specific definitions */ -#include "nimble/nimble_npl_os.h" +#include "nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h" /* * Generic @@ -164,7 +163,7 @@ void ble_npl_time_delay(ble_npl_time_t ticks); #if NIMBLE_CFG_CONTROLLER -void ble_npl_hw_set_isr(int irqn, uint32_t addr); +void ble_npl_hw_set_isr(int irqn, void (*addr)(void)); #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_opt.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/nimble_opt.h similarity index 96% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_opt.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/nimble_opt.h index f0e988b27..7de55d668 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_opt.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/nimble_opt.h @@ -25,7 +25,7 @@ extern "C" { #endif /* Include automatically-generated settings. */ -#include "nimble/nimble_opt_auto.h" +#include "nimble_opt_auto.h" #ifdef __cplusplus } diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_opt_auto.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/nimble_opt_auto.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_opt_auto.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/nimble_opt_auto.h index 33a1e2aac..056eb1b02 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_opt_auto.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/nimble_opt_auto.h @@ -20,7 +20,7 @@ #ifndef H_NIMBLE_OPT_AUTO_ #define H_NIMBLE_OPT_AUTO_ -#include "syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/pkg.yml new file mode 100644 index 000000000..8b6058e11 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/pkg.yml @@ -0,0 +1,30 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: nimble +pkg.description: Generic functionality for the nimble Bluetooth Smart stack; used by both the controller and the host. +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - ble + - bluetooth + +pkg.deps: + - porting/npl/mynewt + - "@apache-mynewt-core/kernel/os" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/syscfg.yml new file mode 100644 index 000000000..537fd9ba5 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/syscfg.yml @@ -0,0 +1,83 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +syscfg.defs: + # Supported GAP roles. By default, all four roles are enabled. + BLE_ROLE_CENTRAL: + description: 'Enables the Central bluetooth role. (0/1)' + value: 1 + BLE_ROLE_PERIPHERAL: + description: 'Enables the Peripheral bluetooth role. (0/1)' + value: 1 + BLE_ROLE_BROADCASTER: + description: 'Enables the Broadcaster bluetooth role. (0/1)' + value: 1 + BLE_ROLE_OBSERVER: + description: 'Enables the Observer bluetooth role. (0/1)' + value: 1 + + BLE_MAX_CONNECTIONS: + description: 'The maximum number of concurrent connections.' + value: 1 + BLE_MAX_PERIODIC_SYNCS: + description: > + The maximum number of concurrent periodic syncs that can + be created + value: 1 + BLE_WHITELIST: + description: > + Enables the BLE whitelist for controlling who to connect to or + accept a connection from. (0/1) + value: 1 + BLE_MULTI_ADV_INSTANCES: + description: > + This is the number of multi-advertising instances. This is NOT the + total number of advertising instances. The total number of + advertising instances is this number plus 1 (assuming the device + supports advertising). + value: 0 + BLE_EXT_ADV: + description: > + This enables extended advertising feature. + value: 0 + BLE_PERIODIC_ADV: + description: > + This enables periodic advertising feature. + value: 0 + BLE_PERIODIC_ADV_SYNC_TRANSFER: + description: > + This enables Periodic Advertising Sync Transfer Feature. + value: 0 + + BLE_EXT_ADV_MAX_SIZE: + description: > + This allows to configure maximum size of advertising data and + scan response data used in LE Advertising Extensions. + Valid range 31-1650. + value: 31 + BLE_VERSION: + description: > + This allows to configure supported Bluetooth Core version. Some + features may not be available if version is too low. Version is + integer for easy comparison. + range: 50, 51, 52 + value: 50 + +# Allow periodic sync transfer only if 5.1 or higher +syscfg.restrictions: + - "'BLE_PERIODIC_ADV_SYNC_TRANSFER == 0' || 'BLE_VERSION >= 51'" diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/pkg.yml new file mode 100644 index 000000000..2bc4ac293 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/pkg.yml @@ -0,0 +1,45 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: nimble/transport +pkg.description: Meta-package for NimBLE HCI transport +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - ble + - bluetooth + +pkg.deps.'BLE_HCI_TRANSPORT == "builtin"': + - nimble/transport/ram + - nimble/controller + +pkg.deps.'BLE_HCI_TRANSPORT == "emspi"': + - nimble/transport/emspi + +pkg.deps.'BLE_HCI_TRANSPORT == "ram"': + - nimble/transport/ram + +pkg.deps.'BLE_HCI_TRANSPORT == "socket"': + - nimble/transport/socket + +pkg.deps.'BLE_HCI_TRANSPORT == "uart"': + - nimble/transport/uart + +pkg.deps.'BLE_HCI_TRANSPORT == "da1469x"': + - nimble/transport/da1469x diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/include/transport/ram/ble_hci_ram.h similarity index 80% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow_priv.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/include/transport/ram/ble_hci_ram.h index 753eaf8ff..00530798d 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow_priv.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/include/transport/ram/ble_hci_ram.h @@ -17,17 +17,16 @@ * under the License. */ -#ifndef H_BLE_HS_FLOW_PRIV_ -#define H_BLE_HS_FLOW_PRIV_ +#ifndef H_BLE_HCI_RAM_ +#define H_BLE_HCI_RAM_ + +#include "nimble/nimble/include/nimble/ble_hci_trans.h" -#include #ifdef __cplusplus extern "C" { #endif -void ble_hs_flow_connection_broken(uint16_t conn_handle); -void ble_hs_flow_track_data_mbuf(struct os_mbuf *om); -int ble_hs_flow_startup(void); +void ble_hci_ram_init(void); #ifdef __cplusplus } diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/pkg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/pkg.yml new file mode 100644 index 000000000..bb8397bf3 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/pkg.yml @@ -0,0 +1,36 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: nimble/transport/ram +pkg.description: XXX +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - ble + - bluetooth + +pkg.deps: + - "@apache-mynewt-core/kernel/os" + - nimble + +pkg.apis: + - ble_transport + +pkg.init: + ble_hci_ram_init: 'MYNEWT_VAL(BLE_TRANS_RAM_SYSINIT_STAGE)' diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/src/ble_hci_ram.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/src/ble_hci_ram.c new file mode 100644 index 000000000..9eaa1d866 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/src/ble_hci_ram.c @@ -0,0 +1,241 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef ESP_PLATFORM + +#include +#include +#include +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/sysinit/sysinit.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/porting/nimble/include/mem/mem.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/include/nimble/ble_hci_trans.h" +#include "../include/transport/ram/ble_hci_ram.h" + +static ble_hci_trans_rx_cmd_fn *ble_hci_ram_rx_cmd_hs_cb; +static void *ble_hci_ram_rx_cmd_hs_arg; + +static ble_hci_trans_rx_cmd_fn *ble_hci_ram_rx_cmd_ll_cb; +static void *ble_hci_ram_rx_cmd_ll_arg; + +static ble_hci_trans_rx_acl_fn *ble_hci_ram_rx_acl_hs_cb; +static void *ble_hci_ram_rx_acl_hs_arg; + +static ble_hci_trans_rx_acl_fn *ble_hci_ram_rx_acl_ll_cb; +static void *ble_hci_ram_rx_acl_ll_arg; + +static struct os_mempool ble_hci_ram_cmd_pool; +static os_membuf_t ble_hci_ram_cmd_buf[ + OS_MEMPOOL_SIZE(1, BLE_HCI_TRANS_CMD_SZ) +]; + +static struct os_mempool ble_hci_ram_evt_hi_pool; +static os_membuf_t ble_hci_ram_evt_hi_buf[ + OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT), + MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE)) +]; + +static struct os_mempool ble_hci_ram_evt_lo_pool; +static os_membuf_t ble_hci_ram_evt_lo_buf[ + OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT), + MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE)) +]; + +void +ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *cmd_cb, + void *cmd_arg, + ble_hci_trans_rx_acl_fn *acl_cb, + void *acl_arg) +{ + ble_hci_ram_rx_cmd_hs_cb = cmd_cb; + ble_hci_ram_rx_cmd_hs_arg = cmd_arg; + ble_hci_ram_rx_acl_hs_cb = acl_cb; + ble_hci_ram_rx_acl_hs_arg = acl_arg; +} + +void +ble_hci_trans_cfg_ll(ble_hci_trans_rx_cmd_fn *cmd_cb, + void *cmd_arg, + ble_hci_trans_rx_acl_fn *acl_cb, + void *acl_arg) +{ + ble_hci_ram_rx_cmd_ll_cb = cmd_cb; + ble_hci_ram_rx_cmd_ll_arg = cmd_arg; + ble_hci_ram_rx_acl_ll_cb = acl_cb; + ble_hci_ram_rx_acl_ll_arg = acl_arg; +} + +int +ble_hci_trans_hs_cmd_tx(uint8_t *cmd) +{ + int rc; + + assert(ble_hci_ram_rx_cmd_ll_cb != NULL); + + rc = ble_hci_ram_rx_cmd_ll_cb(cmd, ble_hci_ram_rx_cmd_ll_arg); + return rc; +} + +int +ble_hci_trans_ll_evt_tx(uint8_t *hci_ev) +{ + int rc; + + assert(ble_hci_ram_rx_cmd_hs_cb != NULL); + + rc = ble_hci_ram_rx_cmd_hs_cb(hci_ev, ble_hci_ram_rx_cmd_hs_arg); + return rc; +} + +int +ble_hci_trans_hs_acl_tx(struct os_mbuf *om) +{ + int rc; + + assert(ble_hci_ram_rx_acl_ll_cb != NULL); + + rc = ble_hci_ram_rx_acl_ll_cb(om, ble_hci_ram_rx_acl_ll_arg); + return rc; +} + +int +ble_hci_trans_ll_acl_tx(struct os_mbuf *om) +{ + int rc; + + assert(ble_hci_ram_rx_acl_hs_cb != NULL); + + rc = ble_hci_ram_rx_acl_hs_cb(om, ble_hci_ram_rx_acl_hs_arg); + return rc; +} + +uint8_t * +ble_hci_trans_buf_alloc(int type) +{ + uint8_t *buf; + + switch (type) { + case BLE_HCI_TRANS_BUF_CMD: + buf = os_memblock_get(&ble_hci_ram_cmd_pool); + break; + + case BLE_HCI_TRANS_BUF_EVT_HI: + buf = os_memblock_get(&ble_hci_ram_evt_hi_pool); + if (buf == NULL) { + /* If no high-priority event buffers remain, try to grab a + * low-priority one. + */ + buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO); + } + break; + + case BLE_HCI_TRANS_BUF_EVT_LO: + buf = os_memblock_get(&ble_hci_ram_evt_lo_pool); + break; + + default: + assert(0); + buf = NULL; + } + + return buf; +} + +void +ble_hci_trans_buf_free(uint8_t *buf) +{ + int rc; + + /* XXX: this may look a bit odd, but the controller uses the command + * buffer to send back the command complete/status as an immediate + * response to the command. This was done to insure that the controller + * could always send back one of these events when a command was received. + * Thus, we check to see which pool the buffer came from so we can free + * it to the appropriate pool + */ + if (os_memblock_from(&ble_hci_ram_evt_hi_pool, buf)) { + rc = os_memblock_put(&ble_hci_ram_evt_hi_pool, buf); + assert(rc == 0); + } else if (os_memblock_from(&ble_hci_ram_evt_lo_pool, buf)) { + rc = os_memblock_put(&ble_hci_ram_evt_lo_pool, buf); + assert(rc == 0); + } else { + assert(os_memblock_from(&ble_hci_ram_cmd_pool, buf)); + rc = os_memblock_put(&ble_hci_ram_cmd_pool, buf); + assert(rc == 0); + } +} + +/** + * Unsupported; the RAM transport does not have a dedicated ACL data packet + * pool. + */ +int +ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_hci_trans_reset(void) +{ + /* No work to do. All allocated buffers are owned by the host or + * controller, and they will get freed by their owners. + */ + return 0; +} + +void +ble_hci_ram_init(void) +{ + int rc; + + /* Ensure this function only gets called by sysinit. */ + SYSINIT_ASSERT_ACTIVE(); + + /* + * Create memory pool of HCI command buffers. NOTE: we currently dont + * allow this to be configured. The controller will only allow one + * outstanding command. We decided to keep this a pool in case we allow + * allow the controller to handle more than one outstanding command. + */ + rc = os_mempool_init(&ble_hci_ram_cmd_pool, + 1, + BLE_HCI_TRANS_CMD_SZ, + ble_hci_ram_cmd_buf, + "ble_hci_ram_cmd_pool"); + SYSINIT_PANIC_ASSERT(rc == 0); + + rc = os_mempool_init(&ble_hci_ram_evt_hi_pool, + MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT), + MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE), + ble_hci_ram_evt_hi_buf, + "ble_hci_ram_evt_hi_pool"); + SYSINIT_PANIC_ASSERT(rc == 0); + + rc = os_mempool_init(&ble_hci_ram_evt_lo_pool, + MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT), + MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE), + ble_hci_ram_evt_lo_buf, + "ble_hci_ram_evt_lo_pool"); + SYSINIT_PANIC_ASSERT(rc == 0); +} + +#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/syscfg.yml new file mode 100644 index 000000000..3b822fcc6 --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/syscfg.yml @@ -0,0 +1,48 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +syscfg.defs: + BLE_HCI_EVT_HI_BUF_COUNT: + description: 'Number of high-priority event buffers.' + value: 2 + + BLE_HCI_EVT_LO_BUF_COUNT: + description: 'Number of low-priority event buffers.' + value: 8 + + BLE_HCI_EVT_BUF_SIZE: + description: 'Size of each event buffer, in bytes.' + value: 70 + + BLE_ACL_BUF_COUNT: + description: 'The number of ACL data buffers' + value: 4 + + BLE_ACL_BUF_SIZE: + description: > + This is the maximum size of the data portion of HCI ACL data + packets. It does not include the HCI data header (of 4 bytes). + value: 255 + + BLE_TRANS_RAM_SYSINIT_STAGE: + description: > + Sysinit stage for the RAM BLE transport. + value: 100 + +syscfg.vals.BLE_EXT_ADV: + BLE_HCI_EVT_BUF_SIZE: 257 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/syscfg.yml b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/syscfg.yml new file mode 100644 index 000000000..137d6e94f --- /dev/null +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/syscfg.yml @@ -0,0 +1,68 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +syscfg.defs: + BLE_HCI_TRANSPORT: + description: > + Selects HCI transport to be included in build. + This has virtually the same effect as including package dependency + manually, but it allows to easily override HCI transport package in + application or target settings. + value: builtin + restrictions: $notnull + choices: + - builtin # Built-in NimBLE controller and RAM transport + - custom # Custom transport, has to be included manually by user + - ram # RAM transport + - uart # UART HCI H4 transport + - socket # Socket transport (for native builds) + - emspi # SPI transport for EM Microelectionic controllers + - da1469x # Dialog DA1469x integrated controller + +# Deprecated settings + BLE_HCI_TRANSPORT_NIMBLE_BUILTIN: + description: Use BLE_HCI_TRANSPORT instead. + value: 0 + deprecated: 1 + BLE_HCI_TRANSPORT_EMSPI: + description: Use BLE_HCI_TRANSPORT instead. + value: 0 + deprecated: 1 + BLE_HCI_TRANSPORT_RAM: + description: Use BLE_HCI_TRANSPORT instead. + value: 0 + deprecated: 1 + BLE_HCI_TRANSPORT_SOCKET: + description: Use BLE_HCI_TRANSPORT instead. + value: 0 + deprecated: 1 + BLE_HCI_TRANSPORT_UART: + description: Use BLE_HCI_TRANSPORT instead. + value: 0 + deprecated: 1 + +syscfg.vals.BLE_HCI_TRANSPORT_NIMBLE_BUILTIN: + BLE_HCI_TRANSPORT: builtin +syscfg.vals.BLE_HCI_TRANSPORT_RAM: + BLE_HCI_TRANSPORT: ram +syscfg.vals.BLE_HCI_TRANSPORT_UART: + BLE_HCI_TRANSPORT: uart +syscfg.vals.BLE_HCI_TRANSPORT_SOCKET: + BLE_HCI_TRANSPORT: socket +syscfg.vals.BLE_HCI_TRANSPORT_EMSPI: + BLE_HCI_TRANSPORT: emspi diff --git a/lib/libesp32_div/NimBLE-Arduino/src/hal/hal_timer.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/hal/hal_timer.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/hal/hal_timer.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/hal/hal_timer.h index be41c6095..936545d8c 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/hal/hal_timer.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/hal/hal_timer.h @@ -29,7 +29,7 @@ #define H_HAL_TIMER_ #include -#include "os/queue.h" +#include "../os/queue.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/log/log.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/log/log.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/log/log.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/log/log.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/log_common/ignore.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/log_common/ignore.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/log_common/ignore.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/log_common/ignore.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/log_common/log_common.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/log_common/log_common.h similarity index 84% rename from lib/libesp32_div/NimBLE-Arduino/src/log_common/log_common.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/log_common/log_common.h index ad79f8905..f6c9e57e0 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/log_common/log_common.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/log_common/log_common.h @@ -20,26 +20,18 @@ #ifndef H_LOG_COMMON_ #define H_LOG_COMMON_ -#include "log_common/ignore.h" +#include "ignore.h" #ifdef __cplusplus extern "C" { #endif -/* #define LOG_LEVEL_DEBUG (0) #define LOG_LEVEL_INFO (1) #define LOG_LEVEL_WARN (2) #define LOG_LEVEL_ERROR (3) #define LOG_LEVEL_CRITICAL (4) #define LOG_LEVEL_NONE (5) -*/ -#define LOG_LEVEL_DEBUG (3) -#define LOG_LEVEL_INFO (2) -#define LOG_LEVEL_WARN (5) -#define LOG_LEVEL_ERROR (1) -#define LOG_LEVEL_CRITICAL (4) -#define LOG_LEVEL_NONE (0) /* Up to 7 custom log levels. */ #define LOG_LEVEL_MAX (15) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/logcfg/logcfg.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/logcfg/logcfg.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/logcfg/logcfg.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/logcfg/logcfg.h index 764f87f27..d7422cc8f 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/logcfg/logcfg.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/logcfg/logcfg.h @@ -5,8 +5,8 @@ #ifndef H_MYNEWT_LOGCFG_ #define H_MYNEWT_LOGCFG_ -#include "modlog/modlog.h" -#include "log_common/log_common.h" +#include "../modlog/modlog.h" +#include "../log_common/log_common.h" #if (MYNEWT_VAL(BLE_HS_LOG_LVL) == LOG_LEVEL_DEBUG) #define BLE_HS_LOG_DEBUG(...) MODLOG_DEBUG(4, __VA_ARGS__) @@ -130,6 +130,7 @@ #define BLE_MESH_TRANS_LOG_ERROR(...) MODLOG_ERROR(21, __VA_ARGS__) #define BLE_MESH_TRANS_LOG_CRITICAL(...) MODLOG_CRITICAL(21, __VA_ARGS__) #define BLE_MESH_TRANS_LOG_DISABLED(...) MODLOG_DISABLED(21, __VA_ARGS__) + #define DFLT_LOG_DEBUG(...) IGNORE(__VA_ARGS__) #define DFLT_LOG_INFO(...) MODLOG_INFO(0, __VA_ARGS__) #define DFLT_LOG_WARN(...) MODLOG_WARN(0, __VA_ARGS__) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/mem/mem.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/mem/mem.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/mem/mem.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/mem/mem.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/modlog/modlog.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/modlog/modlog.h similarity index 79% rename from lib/libesp32_div/NimBLE-Arduino/src/modlog/modlog.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/modlog/modlog.h index e81ea3812..c12b13991 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/modlog/modlog.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/modlog/modlog.h @@ -22,7 +22,8 @@ #include -#include "log/log.h" +#include "../log/log.h" +#include "../log_common/log_common.h" #ifdef ESP_PLATFORM #include "esp_log.h" @@ -32,36 +33,11 @@ #define MODLOG_MODULE_DFLT 255 -#if (MYNEWT_VAL(LOG_LEVEL) > 0) -static inline void -modlog_dummy(const char *msg, ...) -{ - (void)msg; -} -#endif - -#ifdef ESP_PLATFORM +#if defined(ESP_PLATFORM) && !defined(ARDUINO_ARCH_ESP32) #define MODLOG_ESP_LOCAL(level, ml_msg_, ...) do { \ - if (LOG_LOCAL_LEVEL >= level) esp_log_write(level, "NimBLE", ml_msg_, ##__VA_ARGS__); \ + if (MYNEWT_VAL(BLE_HS_LOG_LVL) <= LOG_LOCAL_LEVEL) ESP_LOG_LEVEL_LOCAL(level, "NimBLE", ml_msg_, ##__VA_ARGS__); \ } while(0) -#ifdef ARDUINO_ARCH_ESP32 -#include "nimconfig.h" -#endif - -#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_BT_NIMBLE_DEBUG) - -#define MODLOG_DEBUG(ml_mod_, ml_msg_, ...) \ - MODLOG_ESP_LOCAL(ESP_LOG_ERROR, ml_msg_, ##__VA_ARGS__) - -#define MODLOG_INFO(ml_mod_, ml_msg_, ...) \ - MODLOG_ESP_LOCAL(ESP_LOG_ERROR, ml_msg_, ##__VA_ARGS__) - -#define MODLOG_WARN(ml_mod_, ml_msg_, ...) \ - MODLOG_ESP_LOCAL(ESP_LOG_ERROR, ml_msg_, ##__VA_ARGS__) - -#else - #define MODLOG_DEBUG(ml_mod_, ml_msg_, ...) \ MODLOG_ESP_LOCAL(ESP_LOG_DEBUG, ml_msg_, ##__VA_ARGS__) @@ -71,8 +47,6 @@ modlog_dummy(const char *msg, ...) #define MODLOG_WARN(ml_mod_, ml_msg_, ...) \ MODLOG_ESP_LOCAL(ESP_LOG_WARN, ml_msg_, ##__VA_ARGS__) -#endif - #define MODLOG_ERROR(ml_mod_, ml_msg_, ...) \ MODLOG_ESP_LOCAL(ESP_LOG_ERROR, ml_msg_, ##__VA_ARGS__) @@ -81,12 +55,30 @@ modlog_dummy(const char *msg, ...) #else +#if (MYNEWT_VAL(LOG_LEVEL) > 0) +static inline void +modlog_dummy(const char *msg, ...) +{ + (void)msg; +} +#endif + +#include "nimble/console/console.h" + +#if (MYNEWT_VAL(LOG_LEVEL) > 0) +#define MODLOG_DEBUG(ml_mod_, ml_msg_, ...) \ + modlog_dummy((ml_msg_), ##__VA_ARGS__) +#else +#define MODLOG_DEBUG(ml_mod_, ml_msg_, ...) \ + console_printf((ml_msg_), ##__VA_ARGS__); +#endif + #if (MYNEWT_VAL(LOG_LEVEL) > 1) #define MODLOG_INFO(ml_mod_, ml_msg_, ...) \ modlog_dummy((ml_msg_), ##__VA_ARGS__) #else #define MODLOG_INFO(ml_mod_, ml_msg_, ...) \ - printf((ml_msg_), ##__VA_ARGS__); + console_printf((ml_msg_), ##__VA_ARGS__); #endif #if (MYNEWT_VAL(LOG_LEVEL) > 2) @@ -94,7 +86,7 @@ modlog_dummy(const char *msg, ...) modlog_dummy((ml_msg_), ##__VA_ARGS__) #else #define MODLOG_WARN(ml_mod_, ml_msg_, ...) \ - printf((ml_msg_), ##__VA_ARGS__); + console_printf((ml_msg_), ##__VA_ARGS__); #endif #if (MYNEWT_VAL(LOG_LEVEL) > 3) @@ -102,7 +94,7 @@ modlog_dummy(const char *msg, ...) modlog_dummy((ml_msg_), ##__VA_ARGS__) #else #define MODLOG_ERROR(ml_mod_, ml_msg_, ...) \ - printf((ml_msg_), ##__VA_ARGS__); + console_printf((ml_msg_), ##__VA_ARGS__); #endif #if (MYNEWT_VAL(LOG_LEVEL) > 4) @@ -110,7 +102,7 @@ modlog_dummy(const char *msg, ...) modlog_dummy((ml_msg_), ##__VA_ARGS__) #else #define MODLOG_CRITICAL(ml_mod_, ml_msg_, ...) \ - printf((ml_msg_), ##__VA_ARGS__); + console_printf((ml_msg_), ##__VA_ARGS__); #endif #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_port.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/nimble/nimble_port.h similarity index 88% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_port.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/nimble/nimble_port.h index e8996a666..68e7cdbb8 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_port.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/nimble/nimble_port.h @@ -20,11 +20,16 @@ #ifndef _NIMBLE_PORT_H #define _NIMBLE_PORT_H -#include "nimble/nimble_npl.h" -#include "nimconfig.h" +#include "nimble/nimble/include/nimble/nimble_npl.h" +#ifdef ESP_PLATFORM +#include "nimconfig.h" #define NIMBLE_CORE (CONFIG_BT_NIMBLE_PINNED_TO_CORE < portNUM_PROCESSORS ? CONFIG_BT_NIMBLE_PINNED_TO_CORE : tskNO_AFFINITY) #define NIMBLE_STACK_SIZE CONFIG_BT_NIMBLE_TASK_STACK_SIZE +#else +#include "../syscfg/syscfg.h" +#define NIMBLE_HS_TASK_STACK_SIZE (CONFIG_BT_NIMBLE_TASK_STACK_SIZE / 4) +#endif #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/os/endian.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/endian.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/os/endian.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/endian.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/os/os.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os.h similarity index 89% rename from lib/libesp32_div/NimBLE-Arduino/src/os/os.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os.h index f7a7ef9c5..d4f6101b7 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/os/os.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os.h @@ -34,8 +34,8 @@ extern "C" { #define max(a, b) ((a)>(b)?(a):(b)) #endif -#include "syscfg/syscfg.h" -#include "nimble/nimble_npl.h" +#include "../syscfg/syscfg.h" +#include "nimble/nimble/include/nimble/nimble_npl.h" #define OS_ALIGN(__n, __a) ( \ (((__n) & ((__a) - 1)) == 0) ? \ @@ -50,11 +50,11 @@ typedef uint32_t os_sr_t; #define OS_ASSERT_CRITICAL() assert(ble_npl_hw_is_in_critical()) /* Mynewt components (not abstracted in NPL) */ -#include "os/endian.h" -#include "os/queue.h" -#include "os/os_error.h" -#include "os/os_mbuf.h" -#include "os/os_mempool.h" +#include "endian.h" +#include "queue.h" +#include "os_error.h" +#include "os_mbuf.h" +#include "os_mempool.h" #ifdef __cplusplus } diff --git a/lib/libesp32_div/NimBLE-Arduino/src/os/os_cputime.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_cputime.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/os/os_cputime.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_cputime.h index 20124b574..9002ca56a 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/os/os_cputime.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_cputime.h @@ -31,9 +31,9 @@ extern "C" { #endif -#include "syscfg/syscfg.h" -#include "hal/hal_timer.h" -#include "os/os.h" +#include "../syscfg/syscfg.h" +#include "../hal/hal_timer.h" +#include "os.h" /* * NOTE: these definitions allow one to override the cputime frequency used. diff --git a/lib/libesp32_div/NimBLE-Arduino/src/os/os_error.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_error.h similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/os/os_error.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_error.h index 15cc62282..f2213bdf9 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/os/os_error.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_error.h @@ -20,7 +20,7 @@ #ifndef H_OS_ERROR_ #define H_OS_ERROR_ -#include "os/os.h" +#include "os.h" enum os_error { OS_OK = 0, diff --git a/lib/libesp32_div/NimBLE-Arduino/src/os/os_mbuf.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_mbuf.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/os/os_mbuf.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_mbuf.h index f3857fe46..0775556d2 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/os/os_mbuf.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_mbuf.h @@ -29,7 +29,7 @@ #ifndef _OS_MBUF_H #define _OS_MBUF_H -#include "os/os.h" +#include "os.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/os/os_mempool.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_mempool.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/os/os_mempool.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_mempool.h index 251858742..a01d34ded 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/os/os_mempool.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_mempool.h @@ -29,8 +29,8 @@ #define _OS_MEMPOOL_H_ #include -#include "os/os.h" -#include "os/queue.h" +#include "os.h" +#include "queue.h" #ifdef __cplusplus extern "C" { diff --git a/lib/libesp32_div/NimBLE-Arduino/src/os/os_trace_api.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_trace_api.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/os/os_trace_api.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_trace_api.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/os/queue.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/queue.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/os/queue.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/queue.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/os/util.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/util.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/os/util.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/util.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/stats/stats.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/stats/stats.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/stats/stats.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/stats/stats.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/syscfg/syscfg.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/syscfg/syscfg.h similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/syscfg/syscfg.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/syscfg/syscfg.h index 8dccca5eb..3cb2b14ba 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/syscfg/syscfg.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/syscfg/syscfg.h @@ -6,8 +6,12 @@ #define H_MYNEWT_SYSCFG_ #ifdef ESP_PLATFORM -#include "esp_nimble_cfg.h" +#include "nimble/esp_port/port/include/esp_nimble_cfg.h" #else +#include "ext_nimble_config.h" +#endif + +#if 0 /** * This macro exists to ensure code includes this header when needed. If code diff --git a/lib/libesp32_div/NimBLE-Arduino/src/sysflash/sysflash.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/sysflash/sysflash.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/sysflash/sysflash.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/sysflash/sysflash.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/sysinit/sysinit.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/sysinit/sysinit.h similarity index 100% rename from lib/libesp32_div/NimBLE-Arduino/src/sysinit/sysinit.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/sysinit/sysinit.h diff --git a/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/endian.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/endian.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/endian.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/endian.c index 2afd6a22e..c1b181dfe 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/endian.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/endian.c @@ -17,7 +17,7 @@ * under the License. */ -#include "os/endian.h" +#include "../include/os/endian.h" void put_le16(void *buf, uint16_t x) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/hal_timer.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/hal_timer.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/hal_timer.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/hal_timer.c index 14f746e85..93dfc8df3 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/hal_timer.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/hal_timer.c @@ -16,14 +16,15 @@ * specific language governing permissions and limitations * under the License. */ -#if 0 +#ifndef ESP_PLATFORM + #include #include #include #include -#include "os/os.h" -#include "nrfx.h" -#include "hal/hal_timer.h" +#include "../include/os/os.h" +#include "nrf.h" +#include "../include/hal/hal_timer.h" /* IRQ prototype */ typedef void (*hal_timer_irq_handler_t)(void); @@ -486,9 +487,7 @@ hal_timer_init(int timer_num, void *cfg) /* Disable IRQ, set priority and set vector in table */ NVIC_DisableIRQ(irq_num); -#ifndef RIOT_VERSION NVIC_SetPriority(irq_num, (1 << __NVIC_PRIO_BITS) - 1); -#endif #if MYNEWT NVIC_SetVector(irq_num, (uint32_t)irq_isr); #else diff --git a/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/mem.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/mem.c similarity index 96% rename from lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/mem.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/mem.c index 256632333..bf1ae7ee3 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/mem.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/mem.c @@ -18,9 +18,12 @@ */ #include -#include "os/os.h" -#include "mem/mem.h" -#include "esp_nimble_mem.h" +#include "../include/os/os.h" +#include "../include/mem/mem.h" + +#ifdef ESP_PLATFORM +#include "nimble/esp_port/port/include/esp_nimble_mem.h" +#endif /** * Generic mempool allocation function. Used with basic and extended mempools. @@ -32,7 +35,11 @@ mem_malloc_mempool_gen(uint16_t num_blocks, uint32_t block_size, block_size = OS_ALIGN(block_size, OS_ALIGNMENT); if (num_blocks > 0) { +#ifdef ESP_PLATFORM *out_buf = nimble_platform_mem_malloc(OS_MEMPOOL_BYTES(num_blocks, block_size)); +#else + *out_buf = malloc(OS_MEMPOOL_BYTES(num_blocks, block_size)); +#endif if (*out_buf == NULL) { return OS_ENOMEM; } @@ -73,7 +80,11 @@ mem_malloc_mempool(struct os_mempool *mempool, uint16_t num_blocks, rc = os_mempool_init(mempool, num_blocks, block_size, buf, name); if (rc != 0) { +#ifdef ESP_PLATFORM nimble_platform_mem_free(buf); +#else + free(buf); +#endif return rc; } @@ -114,7 +125,11 @@ mem_malloc_mempool_ext(struct os_mempool_ext *mpe, uint16_t num_blocks, rc = os_mempool_ext_init(mpe, num_blocks, block_size, buf, name); if (rc != 0) { +#ifdef ESP_PLATFORM nimble_platform_mem_free(buf); +#else + free(buf); +#endif return rc; } @@ -161,7 +176,11 @@ mem_malloc_mbuf_pool(struct os_mempool *mempool, rc = os_mbuf_pool_init(mbuf_pool, mempool, block_size, num_blocks); if (rc != 0) { +#ifdef ESP_PLATFORM nimble_platform_mem_free(buf); +#else + free(buf); +#endif return rc; } diff --git a/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/nimble_port.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/nimble_port.c similarity index 90% rename from lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/nimble_port.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/nimble_port.c index 5cd377582..98902ce60 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/nimble_port.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/nimble_port.c @@ -18,12 +18,13 @@ */ #include -#include "os/os.h" -#include "sysinit/sysinit.h" -#include "host/ble_hs.h" -#include "nimble/nimble_port.h" +#include "../include/os/os.h" +#include "../include/sysinit/sysinit.h" +#include "nimble/nimble/host/include/host/ble_hs.h" +#include "../include/nimble/nimble_port.h" + #if NIMBLE_CFG_CONTROLLER -#include "controller/ble_ll.h" +#include "nimble/nimble/controller/include/controller/ble_ll.h" #endif #ifdef ESP_PLATFORM #include "esp_log.h" @@ -38,12 +39,9 @@ void nimble_port_init(void) { void os_msys_init(void); - void ble_store_ram_init(void); + #if NIMBLE_CFG_CONTROLLER void ble_hci_ram_init(void); -#endif -#ifdef ESP_PLATFORM - esp_log_level_set("NimBLE", LOG_LOCAL_LEVEL); #endif /* Initialize default event queue */ ble_npl_eventq_init(&g_eventq_dflt); @@ -52,13 +50,13 @@ nimble_port_init(void) ble_hs_init(); - /* XXX Need to have template for store */ - ble_store_ram_init(); - #if NIMBLE_CFG_CONTROLLER hal_timer_init(5, NULL); + os_cputime_init(32768); + ble_ll_init(); + ble_hci_ram_init(); #endif } diff --git a/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_cputime.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_cputime.c similarity index 96% rename from lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_cputime.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_cputime.c index 6c95c4f19..5c418c6a8 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_cputime.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_cputime.c @@ -20,9 +20,9 @@ #include #include #include -#include "syscfg/syscfg.h" -#include "os/os_cputime.h" -#include "hal/hal_timer.h" +#include "../include/syscfg/syscfg.h" +#include "../include/os/os_cputime.h" +#include "../include/hal/hal_timer.h" #if defined(OS_CPUTIME_FREQ_HIGH) struct os_cputime_data g_os_cputime; diff --git a/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_cputime_pwr2.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_cputime_pwr2.c similarity index 98% rename from lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_cputime_pwr2.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_cputime_pwr2.c index 1567070ae..7a17aabc5 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_cputime_pwr2.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_cputime_pwr2.c @@ -17,7 +17,7 @@ * under the License. */ -#include "os/os_cputime.h" +#include "../include/os/os_cputime.h" /** * This module implements cputime functionality for timers for which: diff --git a/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_mbuf.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_mbuf.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_mbuf.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_mbuf.c index ed18405b8..426bd47d8 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_mbuf.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_mbuf.c @@ -33,7 +33,7 @@ * */ -#include "os/os.h" +#include "../include/os/os.h" #include #include diff --git a/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_mempool.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_mempool.c similarity index 99% rename from lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_mempool.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_mempool.c index ba837e7d6..a26099ef0 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_mempool.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_mempool.c @@ -17,7 +17,7 @@ * under the License. */ -#include "os/os.h" +#include "../include/os/os.h" #include #include diff --git a/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_msys_init.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_msys_init.c similarity index 90% rename from lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_msys_init.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_msys_init.c index 905e7bd09..180e18d60 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/porting/nimble/src/os_msys_init.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_msys_init.c @@ -18,9 +18,12 @@ */ #include -#include "os/os.h" -#include "mem/mem.h" -#include "esp_nimble_mem.h" +#include "../include/os/os.h" +#include "../include/mem/mem.h" + +#ifdef ESP_PLATFORM +#include "nimble/esp_port/port/include/esp_nimble_mem.h" +#endif #if MYNEWT_VAL(MSYS_1_BLOCK_COUNT) > 0 #define SYSINIT_MSYS_1_MEMBLOCK_SIZE \ @@ -28,7 +31,11 @@ #define SYSINIT_MSYS_1_MEMPOOL_SIZE \ OS_MEMPOOL_SIZE(MYNEWT_VAL(MSYS_1_BLOCK_COUNT), \ SYSINIT_MSYS_1_MEMBLOCK_SIZE) +#ifdef ESP_PLATFORM static os_membuf_t *os_msys_init_1_data; +#else +static os_membuf_t os_msys_init_1_data[SYSINIT_MSYS_1_MEMPOOL_SIZE]; +#endif static struct os_mbuf_pool os_msys_init_1_mbuf_pool; static struct os_mempool os_msys_init_1_mempool; #endif @@ -39,7 +46,11 @@ static struct os_mempool os_msys_init_1_mempool; #define SYSINIT_MSYS_2_MEMPOOL_SIZE \ OS_MEMPOOL_SIZE(MYNEWT_VAL(MSYS_2_BLOCK_COUNT), \ SYSINIT_MSYS_2_MEMBLOCK_SIZE) +#ifdef ESP_PLATFORM static os_membuf_t *os_msys_init_2_data; +#else +static os_membuf_t os_msys_init_2_data[SYSINIT_MSYS_2_MEMPOOL_SIZE]; +#endif static struct os_mbuf_pool os_msys_init_2_mbuf_pool; static struct os_mempool os_msys_init_2_mempool; #endif @@ -59,6 +70,7 @@ os_msys_init_once(void *data, struct os_mempool *mempool, assert(rc == 0); } +#ifdef ESP_PLATFORM int os_msys_buf_alloc(void) { @@ -93,6 +105,7 @@ os_msys_buf_free(void) #endif } +#endif void os_msys_init(void) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_npl_os.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h similarity index 89% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_npl_os.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h index f24371653..7321cd27a 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_npl_os.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h @@ -37,6 +37,13 @@ extern "C" { #define BLE_NPL_TIME_FOREVER portMAX_DELAY +#ifndef ESP_PLATFORM +#define NIMBLE_CFG_CONTROLLER 1 +#define NIMBLE_EVT_QUEUE_SIZE 4 +#else +#define NIMBLE_EVT_QUEUE_SIZE 32 +#endif + /* This should be compatible with TickType_t */ typedef uint32_t ble_npl_time_t; typedef int32_t ble_npl_stime_t; @@ -52,7 +59,11 @@ struct ble_npl_eventq { }; struct ble_npl_callout { +#if CONFIG_BT_NIMBLE_USE_ESP_TIMER + esp_timer_handle_t handle; +#else TimerHandle_t handle; +#endif struct ble_npl_eventq *evq; struct ble_npl_event ev; }; @@ -88,7 +99,7 @@ ble_npl_get_current_task_id(void) static inline void ble_npl_eventq_init(struct ble_npl_eventq *evq) { - evq->q = xQueueCreate(32, sizeof(struct ble_npl_eventq *)); + evq->q = xQueueCreate(NIMBLE_EVT_QUEUE_SIZE, sizeof(struct ble_npl_eventq *)); } static inline void @@ -214,6 +225,7 @@ ble_npl_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq, { npl_freertos_callout_init(co, evq, ev_cb, ev_arg); } + static inline void ble_npl_callout_deinit(struct ble_npl_callout *co) { @@ -229,19 +241,19 @@ ble_npl_callout_reset(struct ble_npl_callout *co, ble_npl_time_t ticks) static inline void ble_npl_callout_stop(struct ble_npl_callout *co) { - xTimerStop(co->handle, portMAX_DELAY); + npl_freertos_callout_stop(co); } static inline bool ble_npl_callout_is_active(struct ble_npl_callout *co) { - return xTimerIsTimerActive(co->handle) == pdTRUE; + return npl_freertos_callout_is_active(co); } static inline ble_npl_time_t ble_npl_callout_get_ticks(struct ble_npl_callout *co) { - return xTimerGetExpiryTime(co->handle); + return npl_freertos_callout_get_ticks(co); } static inline uint32_t @@ -295,13 +307,20 @@ ble_npl_time_delay(ble_npl_time_t ticks) #if NIMBLE_CFG_CONTROLLER static inline void -ble_npl_hw_set_isr(int irqn, uint32_t addr) +ble_npl_hw_set_isr(int irqn, void (*addr)(void)) { npl_freertos_hw_set_isr(irqn, addr); } + +static inline bool +ble_npl_hw_is_in_critical(void) +{ + return (uxGetCriticalNestingDepth() > 0); +} #endif -extern portMUX_TYPE ble_port_mutex; +#ifdef ESP_PLATFORM +extern portMUX_TYPE ble_port_mutex; //critical section static inline uint32_t ble_npl_hw_enter_critical(void) @@ -314,9 +333,24 @@ static inline void ble_npl_hw_exit_critical(uint32_t ctx) { portEXIT_CRITICAL(&ble_port_mutex); - } +#else +static inline uint32_t +ble_npl_hw_enter_critical(void) +{ + vPortEnterCritical(); + return 0; +} + +static inline void +ble_npl_hw_exit_critical(uint32_t ctx) +{ + (void)ctx; + vPortExitCritical(); +} +#endif + #ifdef __cplusplus } #endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_port_freertos.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h similarity index 85% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_port_freertos.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h index ddeefc71c..94d75f5a5 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble_port_freertos.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h @@ -20,7 +20,7 @@ #ifndef _NIMBLE_PORT_FREERTOS_H #define _NIMBLE_PORT_FREERTOS_H -#include "nimble/nimble_npl.h" +#include "nimble/nimble/include/nimble/nimble_npl.h" #ifdef __cplusplus extern "C" { @@ -28,6 +28,10 @@ extern "C" { void nimble_port_freertos_init(TaskFunction_t host_task_fn); void nimble_port_freertos_deinit(void); +#ifndef ESP_PLATFORM +UBaseType_t nimble_port_freertos_get_ll_hwm(void); +#endif +UBaseType_t nimble_port_freertos_get_hs_hwm(void); #ifdef __cplusplus } diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/npl_freertos.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/npl_freertos.h similarity index 91% rename from lib/libesp32_div/NimBLE-Arduino/src/nimble/npl_freertos.h rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/npl_freertos.h index 2bf7b3d23..69942773f 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/npl_freertos.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/npl_freertos.h @@ -57,6 +57,12 @@ void npl_freertos_callout_init(struct ble_npl_callout *co, void npl_freertos_callout_deinit(struct ble_npl_callout *co); +void npl_freertos_callout_stop(struct ble_npl_callout *co); + +bool npl_freertos_callout_is_active(struct ble_npl_callout *co); + +ble_npl_time_t npl_freertos_callout_get_ticks(struct ble_npl_callout *co); + ble_npl_error_t npl_freertos_callout_reset(struct ble_npl_callout *co, ble_npl_time_t ticks); @@ -69,7 +75,7 @@ ble_npl_error_t npl_freertos_time_ms_to_ticks(uint32_t ms, ble_npl_error_t npl_freertos_time_ticks_to_ms(ble_npl_time_t ticks, uint32_t *out_ms); -void npl_freertos_hw_set_isr(int irqn, uint32_t addr); +void npl_freertos_hw_set_isr(int irqn, void (*addr)(void)); uint32_t npl_freertos_hw_enter_critical(void); diff --git a/lib/libesp32_div/NimBLE-Arduino/src/porting/npl/freertos/src/nimble_port_freertos.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/src/nimble_port_freertos.c similarity index 61% rename from lib/libesp32_div/NimBLE-Arduino/src/porting/npl/freertos/src/nimble_port_freertos.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/src/nimble_port_freertos.c index f0f80561f..a674e2a56 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/porting/npl/freertos/src/nimble_port_freertos.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/src/nimble_port_freertos.c @@ -20,11 +20,24 @@ #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "nimble/nimble_port.h" +#include "../../../nimble/include/nimble/nimble_port.h" #if NIMBLE_CFG_CONTROLLER +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +#define NIMBLE_LL_TASK_STACK_SIZE (120) +#else +#define NIMBLE_LL_TASK_STACK_SIZE (90) +#endif +static StackType_t ll_xStack[ NIMBLE_LL_TASK_STACK_SIZE ]; +static StaticTask_t ll_xTaskBuffer; static TaskHandle_t ll_task_h; #endif + +#ifndef ESP_PLATFORM +static StackType_t hs_xStack[ NIMBLE_HS_TASK_STACK_SIZE ]; +static StaticTask_t hs_xTaskBuffer; +#endif + static TaskHandle_t host_task_h; void @@ -37,8 +50,8 @@ nimble_port_freertos_init(TaskFunction_t host_task_fn) * provided by NimBLE and in case of FreeRTOS it does not need to be wrapped * since it has compatible prototype. */ - xTaskCreate(nimble_port_ll_task_func, "ll", configMINIMAL_STACK_SIZE + 400, - NULL, configMAX_PRIORITIES - 1, &ll_task_h); + ll_task_h = xTaskCreateStatic(nimble_port_ll_task_func, "ll", NIMBLE_LL_TASK_STACK_SIZE, + NULL, configMAX_PRIORITIES, ll_xStack, &ll_xTaskBuffer); #endif /* @@ -46,8 +59,13 @@ nimble_port_freertos_init(TaskFunction_t host_task_fn) * have separate task for NimBLE host, but since something needs to handle * default queue it is just easier to make separate task which does this. */ +#ifdef ESP_PLATFORM xTaskCreatePinnedToCore(host_task_fn, "ble", NIMBLE_STACK_SIZE, - NULL, (configMAX_PRIORITIES - 4), &host_task_h, NIMBLE_CORE); + NULL, (configMAX_PRIORITIES - 4), &host_task_h, NIMBLE_CORE); +#else + host_task_h = xTaskCreateStatic(host_task_fn, "ble", NIMBLE_HS_TASK_STACK_SIZE, + NULL, (configMAX_PRIORITIES - 1), hs_xStack, &hs_xTaskBuffer); +#endif } void @@ -57,3 +75,17 @@ nimble_port_freertos_deinit(void) vTaskDelete(host_task_h); } } + +#if NIMBLE_CFG_CONTROLLER +UBaseType_t +nimble_port_freertos_get_ll_hwm(void) +{ + return uxTaskGetStackHighWaterMark(ll_task_h); +} +#endif + +UBaseType_t +nimble_port_freertos_get_hs_hwm(void) +{ + return uxTaskGetStackHighWaterMark(host_task_h); +} diff --git a/lib/libesp32_div/NimBLE-Arduino/src/porting/npl/freertos/src/npl_os_freertos.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/src/npl_os_freertos.c similarity index 66% rename from lib/libesp32_div/NimBLE-Arduino/src/porting/npl/freertos/src/npl_os_freertos.c rename to lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/src/npl_os_freertos.c index 07f1294e7..3f9c530e4 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/porting/npl/freertos/src/npl_os_freertos.c +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/src/npl_os_freertos.c @@ -20,11 +20,22 @@ #include #include #include -#include "nimble/nimble_npl.h" -#include "freertos/portable.h" +#include "nimble/nimble/include/nimble/nimble_npl.h" + +#ifdef ESP_PLATFORM +#include "freertos/portable.h" portMUX_TYPE ble_port_mutex = portMUX_INITIALIZER_UNLOCKED; +#else +#include "nrf.h" + +static void *radio_isr_addr; +static void *rng_isr_addr; +static void *rtc0_isr_addr; +#endif + +#ifdef ESP_PLATFORM static inline bool in_isr(void) { @@ -32,6 +43,50 @@ in_isr(void) return xPortInIsrContext() != 0; } +#else +static inline bool +in_isr(void) +{ + /* XXX hw specific! */ + return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0; +} + +void +RADIO_IRQHandler(void) +{ + ((void (*)(void))radio_isr_addr)(); +} + +void +RNG_IRQHandler(void) +{ + ((void (*)(void))rng_isr_addr)(); +} + +void +RTC0_IRQHandler(void) +{ + ((void (*)(void))rtc0_isr_addr)(); +} + +/* This is called by NimBLE radio driver to set interrupt handlers */ +void +npl_freertos_hw_set_isr(int irqn, void (*addr)(void)) +{ + switch (irqn) { + case RADIO_IRQn: + radio_isr_addr = addr; + break; + case RNG_IRQn: + rng_isr_addr = addr; + break; + case RTC0_IRQn: + rtc0_isr_addr = addr; + break; + } +} +#endif + struct ble_npl_event * npl_freertos_eventq_get(struct ble_npl_eventq *evq, ble_npl_time_t tmo) { @@ -42,9 +97,13 @@ npl_freertos_eventq_get(struct ble_npl_eventq *evq, ble_npl_time_t tmo) if (in_isr()) { assert(tmo == 0); ret = xQueueReceiveFromISR(evq->q, &ev, &woken); +#ifdef ESP_PLATFORM if( woken == pdTRUE ) { portYIELD_FROM_ISR(); } +#else + portYIELD_FROM_ISR(woken); +#endif } else { ret = xQueueReceive(evq->q, &ev, tmo); } @@ -71,9 +130,13 @@ npl_freertos_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev) if (in_isr()) { ret = xQueueSendToBackFromISR(evq->q, &ev, &woken); +#ifdef ESP_PLATFORM if( woken == pdTRUE ) { portYIELD_FROM_ISR(); } +#else + portYIELD_FROM_ISR(woken); +#endif } else { ret = xQueueSendToBack(evq->q, &ev, portMAX_DELAY); } @@ -120,13 +183,20 @@ npl_freertos_eventq_remove(struct ble_npl_eventq *evq, woken |= woken2; } +#ifdef ESP_PLATFORM if( woken == pdTRUE ) { portYIELD_FROM_ISR(); } +#else + portYIELD_FROM_ISR(woken); +#endif } else { +#ifdef ESP_PLATFORM portMUX_TYPE ble_npl_mut = portMUX_INITIALIZER_UNLOCKED; portENTER_CRITICAL(&ble_npl_mut); - +#else + vPortEnterCritical(); +#endif count = uxQueueMessagesWaiting(evq->q); for (i = 0; i < count; i++) { ret = xQueueReceive(evq->q, &tmp_ev, 0); @@ -139,8 +209,11 @@ npl_freertos_eventq_remove(struct ble_npl_eventq *evq, ret = xQueueSendToBack(evq->q, &tmp_ev, 0); assert(ret == pdPASS); } - +#ifdef ESP_PLATFORM portEXIT_CRITICAL(&ble_npl_mut); +#else + vPortExitCritical(); +#endif } ev->queued = 0; @@ -256,9 +329,13 @@ npl_freertos_sem_pend(struct ble_npl_sem *sem, ble_npl_time_t timeout) if (in_isr()) { assert(timeout == 0); ret = xSemaphoreTakeFromISR(sem->handle, &woken); +#ifdef ESP_PLATFORM if( woken == pdTRUE ) { portYIELD_FROM_ISR(); } +#else + portYIELD_FROM_ISR(woken); +#endif } else { ret = xSemaphoreTake(sem->handle, timeout); } @@ -280,10 +357,13 @@ npl_freertos_sem_release(struct ble_npl_sem *sem) if (in_isr()) { ret = xSemaphoreGiveFromISR(sem->handle, &woken); - +#ifdef ESP_PLATFORM if( woken == pdTRUE ) { portYIELD_FROM_ISR(); } +#else + portYIELD_FROM_ISR(woken); +#endif } else { ret = xSemaphoreGive(sem->handle); } @@ -292,6 +372,38 @@ npl_freertos_sem_release(struct ble_npl_sem *sem) return BLE_NPL_OK; } + +#if CONFIG_BT_NIMBLE_USE_ESP_TIMER +static void +ble_npl_event_fn_wrapper(void *arg) +{ + struct ble_npl_callout *co = (struct ble_npl_callout *)arg; + + if (co->evq) { + ble_npl_eventq_put(co->evq, &co->ev); + } else { + co->ev.fn(&co->ev); + } +} + +static +ble_npl_error_t esp_err_to_npl_error(esp_err_t err) +{ + switch(err) { + case ESP_ERR_INVALID_ARG: + return BLE_NPL_INVALID_PARAM; + + case ESP_ERR_INVALID_STATE: + return BLE_NPL_EINVAL; + + case ESP_OK: + return BLE_NPL_OK; + + default: + return BLE_NPL_ERROR; + } +} +#else static void os_callout_timer_cb(TimerHandle_t timer) { @@ -306,29 +418,64 @@ os_callout_timer_cb(TimerHandle_t timer) co->ev.fn(&co->ev); } } +#endif void npl_freertos_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq, - ble_npl_event_fn *ev_cb, void *ev_arg) + ble_npl_event_fn *ev_cb, void *ev_arg) { - memset(co, 0, sizeof(*co)); - co->handle = xTimerCreate("co", 1, pdFALSE, co, os_callout_timer_cb); +#if CONFIG_BT_NIMBLE_USE_ESP_TIMER + co->ev.fn = ev_cb; + co->ev.arg = ev_arg; + co->evq = evq; + + esp_timer_create_args_t create_args = { + .callback = ble_npl_event_fn_wrapper, + .arg = co, + .name = "nimble_timer" + }; + + ESP_ERROR_CHECK(esp_timer_create(&create_args, &co->handle)); +#else + if (co->handle == NULL) { + co->handle = xTimerCreate("co", 1, pdFALSE, co, os_callout_timer_cb); + } + co->evq = evq; ble_npl_event_init(&co->ev, ev_cb, ev_arg); +#endif } + void npl_freertos_callout_deinit(struct ble_npl_callout *co) { +#if CONFIG_BT_NIMBLE_USE_ESP_TIMER + ESP_ERROR_CHECK_WITHOUT_ABORT(esp_timer_stop(co->handle)); + ESP_ERROR_CHECK_WITHOUT_ABORT(esp_timer_delete(co->handle)); +#else if (co->handle) { xTimerDelete(co->handle, portMAX_DELAY); + co->handle = NULL; } +#endif } ble_npl_error_t npl_freertos_callout_reset(struct ble_npl_callout *co, ble_npl_time_t ticks) { +#if CONFIG_BT_NIMBLE_USE_ESP_TIMER + esp_timer_stop(co->handle); + + return esp_err_to_npl_error(esp_timer_start_once(co->handle, ticks*1000)); +#else + BaseType_t woken1, woken2, woken3; + if (co->handle == NULL) { + co->handle = xTimerCreate("co", 1, pdFALSE, co, os_callout_timer_cb); + assert(co->handle); + } + if (ticks == 0) { ticks = 1; } @@ -337,10 +484,13 @@ npl_freertos_callout_reset(struct ble_npl_callout *co, ble_npl_time_t ticks) xTimerStopFromISR(co->handle, &woken1); xTimerChangePeriodFromISR(co->handle, ticks, &woken2); xTimerResetFromISR(co->handle, &woken3); - +#ifdef ESP_PLATFORM if( woken1 == pdTRUE || woken2 == pdTRUE || woken3 == pdTRUE) { portYIELD_FROM_ISR(); } +#else + portYIELD_FROM_ISR(woken1 || woken2 || woken3); +#endif } else { xTimerStop(co->handle, portMAX_DELAY); xTimerChangePeriod(co->handle, ticks, portMAX_DELAY); @@ -348,6 +498,49 @@ npl_freertos_callout_reset(struct ble_npl_callout *co, ble_npl_time_t ticks) } return BLE_NPL_OK; +#endif +} + +void +npl_freertos_callout_stop(struct ble_npl_callout *co) +{ +#if CONFIG_BT_NIMBLE_USE_ESP_TIMER + esp_timer_stop(co->handle); +#else + xTimerStop(co->handle, portMAX_DELAY); +#endif +} + +bool +npl_freertos_callout_is_active(struct ble_npl_callout *co) +{ +#if CONFIG_BT_NIMBLE_USE_ESP_TIMER + return esp_timer_is_active(co->handle); +#else + /* Workaround for bug in xTimerIsTimerActive with FreeRTOS V10.2.0, fixed in V10.4.4 + * See: https://github.com/FreeRTOS/FreeRTOS-Kernel/pull/305 + * Sometimes xTimerIsTimerActive returns pdTRUE even though the timer has expired, so we double check. + */ + return xTimerIsTimerActive(co->handle) == pdTRUE && xTimerGetExpiryTime(co->handle) > xTaskGetTickCountFromISR(); +#endif +} + +ble_npl_time_t +npl_freertos_callout_get_ticks(struct ble_npl_callout *co) +{ +#if CONFIG_BT_NIMBLE_USE_ESP_TIMER + /* Currently, esp_timer does not support an API which gets the expiry time for + * current timer. + * Returning 0 from here should not cause any effect. + * Drawback of this approach is that existing code to reset timer would be called + * more often (since the if condition to invoke reset timer would always succeed if + * timer is active). + */ + + return 0; +#else + return xTimerGetExpiryTime(co->handle); +#endif } ble_npl_time_t diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimconfig.h b/lib/libesp32_div/NimBLE-Arduino/src/nimconfig.h index cf7711c08..b66993ef7 100644 --- a/lib/libesp32_div/NimBLE-Arduino/src/nimconfig.h +++ b/lib/libesp32_div/NimBLE-Arduino/src/nimconfig.h @@ -1,6 +1,11 @@ #pragma once +#ifdef ESP_PLATFORM #include "sdkconfig.h" +#else +#include "ext_nimble_config.h" +#endif + #include "nimconfig_rename.h" /*********************************************** @@ -16,10 +21,17 @@ /** @brief Un-comment to change default device name */ // #define CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME "nimble" -/** @brief Un-comment to see debug log messages from the NimBLE host +/** @brief Un-comment to set the debug log messages level from the NimBLE host stack.\n + * Values: 0 = DEBUG, 1 = INFO, 2 = WARNING, 3 = ERROR, 4 = CRITICAL, 5+ = NONE\n * Uses approx. 32kB of flash memory. */ -// #define CONFIG_BT_NIMBLE_DEBUG + // #define CONFIG_BT_NIMBLE_LOG_LEVEL 5 + + /** @brief Un-comment to set the debug log messages level from the NimBLE CPP Wrapper.\n + * Values: 0 = NONE, 1 = ERROR, 2 = WARNING, 3 = INFO, 4+ = DEBUG\n + * Uses approx. 32kB of flash memory. + */ + // #define NIMBLE_CPP_DEBUG_LEVEL 0 /** @brief Un-comment to see NimBLE host return codes as text debug log messages. * Uses approx. 7kB of flash memory. @@ -150,6 +162,10 @@ #define CONFIG_BT_NIMBLE_RPA_TIMEOUT 900 #endif +#ifndef CONFIG_BT_NIMBLE_LOG_LEVEL +#define CONFIG_BT_NIMBLE_LOG_LEVEL 5 +#endif + /** @brief Set if CCCD's and bond data should be stored in NVS */ #define CONFIG_BT_NIMBLE_NVS_PERSIST 1 @@ -192,14 +208,27 @@ #define CONFIG_BT_ENABLED #endif +#ifdef ESP_PLATFORM #ifndef CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY #define CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY #endif +#ifndef CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE +#define CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE 0 +#endif + +#ifndef CONFIG_BTDM_SCAN_DUPL_TYPE_DATA +#define CONFIG_BTDM_SCAN_DUPL_TYPE_DATA 1 +#endif + +#ifndef CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE +#define CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE 2 +#endif #if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) #define CONFIG_IDF_TARGET_ESP32 1 #endif +#endif /* Cannot use client without scan */ #if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) && !defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) diff --git a/lib/libesp32_div/NimBLE-Arduino/src/src/ble_hs_hci_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/src/ble_hs_hci_priv.h deleted file mode 100644 index 362f12cbd..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/src/ble_hs_hci_priv.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_HS_HCI_PRIV_ -#define H_BLE_HS_HCI_PRIV_ - -#include "nimble/hci_common.h" -#ifdef __cplusplus -extern "C" { -#endif - -struct ble_hs_conn; -struct os_mbuf; - -#define BLE_HS_HCI_LE_FEAT_ENCRYPTION (0x00000001) -#define BLE_HS_HCI_LE_FEAT_CONN_PARAM_REQUEST (0x00000002) -#define BLE_HS_HCI_LE_FEAT_EXT_REJECT (0x00000004) -#define BLE_HS_HCI_LE_FEAT_SLAVE_FEAT_EXCHANGE (0x00000008) -#define BLE_HS_HCI_LE_FEAT_PING (0x00000010) -#define BLE_HS_HCI_LE_FEAT_DATA_PACKET_LENGTH_EXT (0x00000020) -#define BLE_HS_HCI_LE_FEAT_LL_PRIVACY (0x00000040) -#define BLE_HS_HCI_LE_FEAT_EXT_SCANNER_FILTER_POLICIES (0x00000080) -#define BLE_HS_HCI_LE_FEAT_2M_PHY (0x00000100) -#define BLE_HS_HCI_LE_FEAT_STABLE_MOD_INDEX_TX (0x00000200) -#define BLE_HS_HCI_LE_FEAT_STABLE_MOD_INDEX_RX (0x00000400) -#define BLE_HS_HCI_LE_FEAT_CODED_PHY (0x00000800) -#define BLE_HS_HCI_LE_FEAT_EXT_ADV (0x00001000) -#define BLE_HS_HCI_LE_FEAT_PERIODIC_ADV (0x00002000) -#define BLE_HS_HCI_LE_FEAT_CSA2 (0x00004000) -#define BLE_HS_HCI_LE_FEAT_POWER_CLASS_1 (0x00008000) -#define BLE_HS_HCI_LE_FEAT_MIN_NUM_USED_CHAN (0x00010000) - -struct ble_hs_hci_ack { - int bha_status; /* A BLE_HS_E<...> error; NOT a naked HCI code. */ - const uint8_t *bha_params; - int bha_params_len; - uint16_t bha_opcode; - uint8_t bha_hci_handle; -}; - -#if MYNEWT_VAL(BLE_EXT_ADV) -struct ble_hs_hci_ext_scan_param { - uint8_t scan_type; - uint16_t scan_itvl; - uint16_t scan_window; -}; - -struct ble_hs_hci_ext_conn_params { - uint16_t scan_itvl; - uint16_t scan_window; - uint16_t conn_itvl; - uint16_t conn_windows; -}; - -#if MYNEWT_VAL(BLE_PERIODIC_ADV) -/* Periodic Advertising Parameters */ -struct hci_periodic_adv_params -{ - uint16_t min_interval; - uint16_t max_interval; - uint16_t properties; -}; -#endif -#endif - -extern uint16_t ble_hs_hci_avail_pkts; - -int ble_hs_hci_cmd_tx(uint16_t opcode, const void *cmd, uint8_t cmd_len, - void *rsp, uint8_t rsp_len); -void ble_hs_hci_init(void); -void ble_hs_hci_deinit(void); - -void ble_hs_hci_set_le_supported_feat(uint32_t feat); -uint32_t ble_hs_hci_get_le_supported_feat(void); -void ble_hs_hci_set_hci_version(uint8_t hci_version); -uint8_t ble_hs_hci_get_hci_version(void); - -#if MYNEWT_VAL(BLE_HS_PHONY_HCI_ACKS) -typedef int ble_hs_hci_phony_ack_fn(uint8_t *ack, int ack_buf_len); -void ble_hs_hci_set_phony_ack_cb(ble_hs_hci_phony_ack_fn *cb); -#endif - -int ble_hs_hci_util_read_adv_tx_pwr(int8_t *out_pwr); -int ble_hs_hci_util_rand(void *dst, int len); -int ble_hs_hci_util_read_rssi(uint16_t conn_handle, int8_t *out_rssi); -int ble_hs_hci_util_set_random_addr(const uint8_t *addr); -int ble_hs_hci_util_data_hdr_strip(struct os_mbuf *om, - struct hci_data_hdr *out_hdr); -int ble_hs_hci_evt_process(const struct ble_hci_ev *ev); - -int ble_hs_hci_cmd_send_buf(uint16_t opcode, const void *buf, uint8_t buf_len); -int ble_hs_hci_set_buf_sz(uint16_t pktlen, uint16_t max_pkts); -void ble_hs_hci_add_avail_pkts(uint16_t delta); - -uint16_t ble_hs_hci_util_handle_pb_bc_join(uint16_t handle, uint8_t pb, - uint8_t bc); - -int ble_hs_hci_acl_tx_now(struct ble_hs_conn *conn, struct os_mbuf **om); -int ble_hs_hci_acl_tx(struct ble_hs_conn *conn, struct os_mbuf **om); - -int ble_hs_hci_frag_num_mbufs(void); -int ble_hs_hci_frag_num_mbufs_free(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/src/ble_sm_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/src/ble_sm_priv.h deleted file mode 100644 index def0a32f5..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/src/ble_sm_priv.h +++ /dev/null @@ -1,428 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_SM_PRIV_ -#define H_BLE_SM_PRIV_ - -#include -#include "syscfg/syscfg.h" -#include "os/queue.h" -#include "nimble/nimble_opt.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct ble_gap_sec_state; -struct hci_le_lt_key_req; -struct hci_encrypt_change; - -#define BLE_SM_MTU 65 - -#define BLE_SM_OP_PAIR_REQ 0x01 -#define BLE_SM_OP_PAIR_RSP 0x02 -#define BLE_SM_OP_PAIR_CONFIRM 0x03 -#define BLE_SM_OP_PAIR_RANDOM 0x04 -#define BLE_SM_OP_PAIR_FAIL 0x05 -#define BLE_SM_OP_ENC_INFO 0x06 -#define BLE_SM_OP_MASTER_ID 0x07 -#define BLE_SM_OP_IDENTITY_INFO 0x08 -#define BLE_SM_OP_IDENTITY_ADDR_INFO 0x09 -#define BLE_SM_OP_SIGN_INFO 0x0a -#define BLE_SM_OP_SEC_REQ 0x0b -#define BLE_SM_OP_PAIR_PUBLIC_KEY 0x0c -#define BLE_SM_OP_PAIR_DHKEY_CHECK 0x0d -#define BLE_SM_OP_PAIR_KEYPRESS_NOTIFY 0x0e - -struct ble_sm_hdr { - uint8_t opcode; - uint8_t data[0]; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | (Code=0x01/0x02 [req/rsp]) | 1 | - * | IO Capability | 1 | - * | OOB data flag | 1 | - * | AuthReq | 1 | - * | Maximum Encryption Key Size | 1 | - * | Initiator Key Distribution | 1 | - * | Responder Key Distribution | 1 | - */ - -struct ble_sm_pair_cmd { - uint8_t io_cap; - uint8_t oob_data_flag; - uint8_t authreq; - uint8_t max_enc_key_size; - uint8_t init_key_dist; - uint8_t resp_key_dist; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | (Code=0x03) | 1 | - * | Confirm Value | 16 | - */ - -struct ble_sm_pair_confirm { - uint8_t value[16]; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | (Code=0x04) | 1 | - * | Random Value | 16 | - */ -struct ble_sm_pair_random { - uint8_t value[16]; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | (Code=0x05) | 1 | - * | Reason | 1 | - */ -struct ble_sm_pair_fail { - uint8_t reason; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | (Code=0x06) | 1 | - * | ltk | 16 | - */ -struct ble_sm_enc_info { - uint8_t ltk[16]; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | (Code=0x07) | 1 | - * | EDIV | 2 | - * | RAND | 8 | - */ -struct ble_sm_master_id { - uint16_t ediv; - uint64_t rand_val; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | (Code=0x08) | 1 | - * | irk | 16 | - */ -struct ble_sm_id_info { - uint8_t irk[16]; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | (Code=0x09) | 1 | - * | addr_type | 1 | - * | address | 6 | - */ -struct ble_sm_id_addr_info { - uint8_t addr_type; - uint8_t bd_addr[6]; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | (Code=0x0A) | 1 | - * | csrk | 16 | - */ -struct ble_sm_sign_info { - uint8_t sig_key[16]; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | (Code=0x0B) | 1 | - * | authreq | 1 | - */ -struct ble_sm_sec_req { - uint8_t authreq; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | (Code=0x0c) | 1 | - * | Public Key X | 32 | - * | Public Key Y | 32 | - */ -struct ble_sm_public_key { - uint8_t x[32]; - uint8_t y[32]; -} __attribute__((packed)); - -/** - * | Parameter | Size (octets) | - * +------------------------------------+-------------------+ - * | (Code=0x0d) | 1 | - * | DHKey Check | 16 | - */ -struct ble_sm_dhkey_check { - uint8_t value[16]; -} __attribute__((packed)); - -#if NIMBLE_BLE_SM - -#define BLE_SM_PROC_STATE_NONE ((uint8_t)-1) - -#define BLE_SM_PROC_STATE_PAIR 0 -#define BLE_SM_PROC_STATE_CONFIRM 1 -#define BLE_SM_PROC_STATE_RANDOM 2 -#define BLE_SM_PROC_STATE_LTK_START 3 -#define BLE_SM_PROC_STATE_LTK_RESTORE 4 -#define BLE_SM_PROC_STATE_ENC_START 5 -#define BLE_SM_PROC_STATE_ENC_RESTORE 6 -#define BLE_SM_PROC_STATE_KEY_EXCH 7 -#define BLE_SM_PROC_STATE_SEC_REQ 8 -#define BLE_SM_PROC_STATE_PUBLIC_KEY 9 -#define BLE_SM_PROC_STATE_DHKEY_CHECK 10 -#define BLE_SM_PROC_STATE_CNT 11 - -#define BLE_SM_PROC_F_INITIATOR 0x01 -#define BLE_SM_PROC_F_IO_INJECTED 0x02 -#define BLE_SM_PROC_F_ADVANCE_ON_IO 0x04 -#define BLE_SM_PROC_F_AUTHENTICATED 0x08 -#define BLE_SM_PROC_F_SC 0x10 -#define BLE_SM_PROC_F_BONDING 0x20 - -#define BLE_SM_KE_F_ENC_INFO 0x01 -#define BLE_SM_KE_F_MASTER_ID 0x02 -#define BLE_SM_KE_F_ID_INFO 0x04 -#define BLE_SM_KE_F_ADDR_INFO 0x08 -#define BLE_SM_KE_F_SIGN_INFO 0x10 - -typedef uint8_t ble_sm_proc_flags; - -struct ble_sm_keys { - unsigned ltk_valid:1; - unsigned ediv_rand_valid:1; - unsigned irk_valid:1; - unsigned csrk_valid:1; - unsigned addr_valid:1; - uint16_t ediv; - uint64_t rand_val; - uint8_t addr_type; - uint8_t key_size; - uint8_t ltk[16]; /* Little endian. */ - uint8_t irk[16]; /* Little endian. */ - uint8_t csrk[16]; /* Little endian. */ - uint8_t addr[6]; /* Little endian. */ -}; - -struct ble_sm_proc { - STAILQ_ENTRY(ble_sm_proc) next; - - ble_npl_time_t exp_os_ticks; - ble_sm_proc_flags flags; - uint16_t conn_handle; - uint8_t pair_alg; - uint8_t state; - uint8_t rx_key_flags; - uint8_t key_size; - - uint8_t pair_req[sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_pair_cmd)]; - uint8_t pair_rsp[sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_pair_cmd)]; - uint8_t tk[16]; - uint8_t confirm_peer[16]; - uint8_t randm[16]; - uint8_t rands[16]; - uint8_t ltk[16]; /* Little endian. */ - struct ble_sm_keys our_keys; - struct ble_sm_keys peer_keys; - -#if MYNEWT_VAL(BLE_SM_SC) - /* Secure connections. */ - uint8_t passkey_bits_exchanged; - uint8_t ri; - struct ble_sm_public_key pub_key_peer; - uint8_t mackey[16]; - uint8_t dhkey[32]; - const struct ble_sm_sc_oob_data *oob_data_local; - const struct ble_sm_sc_oob_data *oob_data_remote; -#endif -}; - -struct ble_sm_result { - int app_status; - uint8_t sm_err; - struct ble_gap_passkey_params passkey_params; - void *state_arg; - unsigned execute : 1; - unsigned enc_cb : 1; - unsigned bonded : 1; - unsigned restore : 1; -}; - -#if MYNEWT_VAL(BLE_HS_DEBUG) -void ble_sm_dbg_set_next_pair_rand(uint8_t *next_pair_rand); -void ble_sm_dbg_set_next_ediv(uint16_t next_ediv); -void ble_sm_dbg_set_next_master_id_rand(uint64_t next_master_id_rand); -void ble_sm_dbg_set_next_ltk(uint8_t *next_ltk); -void ble_sm_dbg_set_next_csrk(uint8_t *next_csrk); -void ble_sm_dbg_set_sc_keys(uint8_t *pubkey, uint8_t *privkey); -#endif - -int ble_sm_num_procs(void); - -int ble_sm_alg_s1(const uint8_t *k, const uint8_t *r1, const uint8_t *r2, - uint8_t *out); -int ble_sm_alg_c1(const uint8_t *k, const uint8_t *r, - const uint8_t *preq, const uint8_t *pres, - uint8_t iat, uint8_t rat, - const uint8_t *ia, const uint8_t *ra, - uint8_t *out_enc_data); -int ble_sm_alg_f4(const uint8_t *u, const uint8_t *v, const uint8_t *x, - uint8_t z, uint8_t *out_enc_data); -int ble_sm_alg_g2(const uint8_t *u, const uint8_t *v, const uint8_t *x, - const uint8_t *y, uint32_t *passkey); -int ble_sm_alg_f5(const uint8_t *w, const uint8_t *n1, const uint8_t *n2, - uint8_t a1t, const uint8_t *a1, uint8_t a2t, - const uint8_t *a2, uint8_t *mackey, uint8_t *ltk); -int ble_sm_alg_f6(const uint8_t *w, const uint8_t *n1, const uint8_t *n2, - const uint8_t *r, const uint8_t *iocap, uint8_t a1t, - const uint8_t *a1, uint8_t a2t, const uint8_t *a2, - uint8_t *check); -int ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, - const uint8_t *peer_pub_key_y, - const uint8_t *our_priv_key, uint8_t *out_dhkey); -int ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv); -void ble_sm_alg_ecc_init(void); - -void ble_sm_enc_change_rx(const struct ble_hci_ev_enrypt_chg *ev); -void ble_sm_enc_key_refresh_rx(const struct ble_hci_ev_enc_key_refresh *ev); -int ble_sm_ltk_req_rx(const struct ble_hci_ev_le_subev_lt_key_req *ev); - -#if MYNEWT_VAL(BLE_SM_LEGACY) -int ble_sm_lgcy_io_action(struct ble_sm_proc *proc, uint8_t *action); -void ble_sm_lgcy_confirm_exec(struct ble_sm_proc *proc, - struct ble_sm_result *res); -void ble_sm_lgcy_random_exec(struct ble_sm_proc *proc, - struct ble_sm_result *res); -void ble_sm_lgcy_random_rx(struct ble_sm_proc *proc, - struct ble_sm_result *res); -#else -#define ble_sm_lgcy_io_action(proc, action) (BLE_HS_ENOTSUP) -#define ble_sm_lgcy_confirm_exec(proc, res) -#define ble_sm_lgcy_random_exec(proc, res) -#define ble_sm_lgcy_random_rx(proc, res) -#endif - -#if MYNEWT_VAL(BLE_SM_SC) -int ble_sm_sc_io_action(struct ble_sm_proc *proc, uint8_t *action); -void ble_sm_sc_confirm_exec(struct ble_sm_proc *proc, - struct ble_sm_result *res); -void ble_sm_sc_random_exec(struct ble_sm_proc *proc, - struct ble_sm_result *res); -void ble_sm_sc_random_rx(struct ble_sm_proc *proc, struct ble_sm_result *res); -void ble_sm_sc_public_key_exec(struct ble_sm_proc *proc, - struct ble_sm_result *res, - void *arg); -void ble_sm_sc_public_key_rx(uint16_t conn_handle, struct os_mbuf **rxom, - struct ble_sm_result *res); -void ble_sm_sc_dhkey_check_exec(struct ble_sm_proc *proc, - struct ble_sm_result *res, void *arg); -void ble_sm_sc_dhkey_check_rx(uint16_t conn_handle, struct os_mbuf **rxom, - struct ble_sm_result *res); -bool ble_sm_sc_oob_data_check(struct ble_sm_proc *proc, - bool oob_data_local_present, - bool oob_data_remote_present); -void ble_sm_sc_oob_confirm(struct ble_sm_proc *proc, struct ble_sm_result *res); -void ble_sm_sc_init(void); -#else -#define ble_sm_sc_io_action(proc, action) (BLE_HS_ENOTSUP) -#define ble_sm_sc_confirm_exec(proc, res) -#define ble_sm_sc_random_exec(proc, res) -#define ble_sm_sc_random_rx(proc, res) -#define ble_sm_sc_public_key_exec(proc, res, arg) -#define ble_sm_sc_public_key_rx(conn_handle, op, om, res) -#define ble_sm_sc_dhkey_check_exec(proc, res, arg) -#define ble_sm_sc_dhkey_check_rx(conn_handle, op, om, res) -#define ble_sm_sc_init() - -#endif - -struct ble_sm_proc *ble_sm_proc_find(uint16_t conn_handle, uint8_t state, - int is_initiator, - struct ble_sm_proc **out_prev); -int ble_sm_gen_pair_rand(uint8_t *pair_rand); -uint8_t *ble_sm_our_pair_rand(struct ble_sm_proc *proc); -uint8_t *ble_sm_peer_pair_rand(struct ble_sm_proc *proc); -int ble_sm_ioact_state(uint8_t action); -int ble_sm_proc_can_advance(struct ble_sm_proc *proc); -void ble_sm_process_result(uint16_t conn_handle, struct ble_sm_result *res); -void ble_sm_confirm_advance(struct ble_sm_proc *proc); -void ble_sm_ia_ra(struct ble_sm_proc *proc, - uint8_t *out_iat, uint8_t *out_ia, - uint8_t *out_rat, uint8_t *out_ra); - -int32_t ble_sm_timer(void); -void ble_sm_connection_broken(uint16_t conn_handle); -int ble_sm_pair_initiate(uint16_t conn_handle); -int ble_sm_slave_initiate(uint16_t conn_handle); -int ble_sm_enc_initiate(uint16_t conn_handle, uint8_t key_size, - const uint8_t *ltk, uint16_t ediv, - uint64_t rand_val, int auth); -int ble_sm_alg_encrypt(const uint8_t *key, const uint8_t *plaintext, - uint8_t *enc_data); -int ble_sm_init(void); -#else - -#define ble_sm_enc_change_rx(evt) ((void)(evt)) -#define ble_sm_ltk_req_rx(evt) ((void)(evt)) -#define ble_sm_enc_key_refresh_rx(evt) ((void)(evt)) - -#define ble_sm_timer() BLE_HS_FOREVER -#define ble_sm_connection_broken(conn_handle) -#define ble_sm_pair_initiate(conn_handle) BLE_HS_ENOTSUP -#define ble_sm_slave_initiate(conn_handle) BLE_HS_ENOTSUP -#define ble_sm_enc_initiate(conn_handle, keysize, ltk, ediv, rand_val, auth) \ - BLE_HS_ENOTSUP - -#define ble_sm_init() 0 - -#define ble_sm_alg_encrypt(key, plaintext, enc_data) \ - BLE_HS_ENOTSUP - -#endif - -struct ble_l2cap_chan *ble_sm_create_chan(uint16_t handle); -void *ble_sm_cmd_get(uint8_t opcode, size_t len, struct os_mbuf **txom); -int ble_sm_tx(uint16_t conn_handle, struct os_mbuf *txom); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/store/ram/ble_store_ram.h b/lib/libesp32_div/NimBLE-Arduino/src/store/ram/ble_store_ram.h deleted file mode 100644 index 842fb5f3f..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/store/ram/ble_store_ram.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_STORE_RAM_ -#define H_BLE_STORE_RAM_ - -#ifdef __cplusplus -extern "C" { -#endif - -union ble_store_key; -union ble_store_value; - -int ble_store_ram_read(int obj_type, const union ble_store_key *key, - union ble_store_value *value); -int ble_store_ram_write(int obj_type, const union ble_store_value *val); -int ble_store_ram_delete(int obj_type, const union ble_store_key *key); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/AUTHORS b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/AUTHORS deleted file mode 100644 index 0a8e9f806..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/AUTHORS +++ /dev/null @@ -1,15 +0,0 @@ -Architect: -Rafael Misoczki - -Open Source Maintainer: -Constanza Heath -Rafael Misoczki - -Contributors: -Constanza Heath -Rafael Misoczki -Flavio Santes -Jarkko Sakkinen -Chris Morrison -Marti Bolivar -Colin Ian King diff --git a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/LICENSE b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/LICENSE deleted file mode 100644 index 2e1db516a..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/LICENSE +++ /dev/null @@ -1,61 +0,0 @@ - -================================================================================ - - TinyCrypt Cryptographic Library - -================================================================================ - - Copyright (c) 2017, Intel Corporation. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - - Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - - Neither the name of the Intel Corporation nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -================================================================================ -Copyright (c) 2014, Kenneth MacKay -All rights reserved. - -https://github.com/kmackay/micro-ecc - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -================================================================================ diff --git a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/README b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/README deleted file mode 100644 index fb52c196a..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/README +++ /dev/null @@ -1,71 +0,0 @@ - -================================================================================ - - TinyCrypt Cryptographic Library - -================================================================================ - - Copyright (c) 2017, Intel Corporation. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - - Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - - Neither the name of the Intel Corporation nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -================================================================================ - -Overview: - -The TinyCrypt Library provides an implementation for constrained devices of a -minimal set of standard cryptography primitives. - -Please, ***SEE THE DOCUMENTATION*** folder for more information on the supported -cryptographic primitives and the limitations of TinyCrypt library. For usage, -security and technicalities, please see the corresponding header file of each -cryptographic primitive. - -================================================================================ - -Organization: - -/lib: C source code of the cryptographic primitives. -/lib/include/tinycrypt: C header files of the cryptographic primitives. -/tests: Test vectors of the cryptographic primitives. -/doc: Documentation of TinyCrypt. - -================================================================================ - -Building: - -1) In Makefile.conf set: - - CFLAGS for compiler flags. - - CC for compiler. - - ENABLE_TESTS for enabling (true) or disabling (false) tests compilation. -2) In lib/Makefile select the primitives required by your project. -3) In tests/Makefile select the corresponding tests of the selected primitives. -4) make -5) run tests in tests/ - -================================================================================ - diff --git a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/VERSION b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/VERSION deleted file mode 100644 index a45be4627..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/VERSION +++ /dev/null @@ -1 +0,0 @@ -0.2.8 diff --git a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/documentation/tinycrypt.rst b/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/documentation/tinycrypt.rst deleted file mode 100644 index 356c099a0..000000000 --- a/lib/libesp32_div/NimBLE-Arduino/src/tinycrypt/documentation/tinycrypt.rst +++ /dev/null @@ -1,352 +0,0 @@ - -TinyCrypt Cryptographic Library -############################### -Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - -Overview -******** -The TinyCrypt Library provides an implementation for targeting constrained devices -with a minimal set of standard cryptography primitives, as listed below. To better -serve applications targeting constrained devices, TinyCrypt implementations differ -from the standard specifications (see the Important Remarks section for some -important differences). Certain cryptographic primitives depend on other -primitives, as mentioned in the list below. - -Aside from the Important Remarks section below, valuable information on the usage, -security and technicalities of each cryptographic primitive are found in the -corresponding header file. - -* SHA-256: - - * Type of primitive: Hash function. - * Standard Specification: NIST FIPS PUB 180-4. - * Requires: -- - -* HMAC-SHA256: - - * Type of primitive: Message authentication code. - * Standard Specification: RFC 2104. - * Requires: SHA-256 - -* HMAC-PRNG: - - * Type of primitive: Pseudo-random number generator (256-bit strength). - * Standard Specification: NIST SP 800-90A. - * Requires: SHA-256 and HMAC-SHA256. - -* AES-128: - - * Type of primitive: Block cipher. - * Standard Specification: NIST FIPS PUB 197. - * Requires: -- - -* AES-CBC mode: - - * Type of primitive: Encryption mode of operation. - * Standard Specification: NIST SP 800-38A. - * Requires: AES-128. - -* AES-CTR mode: - - * Type of primitive: Encryption mode of operation. - * Standard Specification: NIST SP 800-38A. - * Requires: AES-128. - -* AES-CMAC mode: - - * Type of primitive: Message authentication code. - * Standard Specification: NIST SP 800-38B. - * Requires: AES-128. - -* AES-CCM mode: - - * Type of primitive: Authenticated encryption. - * Standard Specification: NIST SP 800-38C. - * Requires: AES-128. - -* CTR-PRNG: - - * Type of primitive: Pseudo-random number generator (128-bit strength). - * Standard Specification: NIST SP 800-90A. - * Requires: AES-128. - -* ECC-DH: - - * Type of primitive: Key exchange based on curve NIST p-256. - * Standard Specification: RFC 6090. - * Requires: ECC auxiliary functions (ecc.h/c). - -* ECC-DSA: - - * Type of primitive: Digital signature based on curve NIST p-256. - * Standard Specification: RFC 6090. - * Requires: ECC auxiliary functions (ecc.h/c). - -Design Goals -************ - -* Minimize the code size of each cryptographic primitive. This means minimize - the size of a platform-independent implementation, as presented in TinyCrypt. - Note that various applications may require further features, optimizations with - respect to other metrics and countermeasures for particular threats. These - peculiarities would increase the code size and thus are not considered here. - -* Minimize the dependencies among the cryptographic primitives. This means - that it is unnecessary to build and allocate object code for more primitives - than the ones strictly required by the intended application. In other words, - one can select and compile only the primitives required by the application. - - -Important Remarks -***************** - -The cryptographic implementations in TinyCrypt library have some limitations. -Some of these limitations are inherent to the cryptographic primitives -themselves, while others are specific to TinyCrypt. These limitations were accepted -in order to meet its design goals (in special, minimal code size) and to better -serve applications targeting constrained devices in general. Some of these -limitations are discussed in-depth below. - -General Remarks -*************** - -* TinyCrypt does **not** intend to be fully side-channel resistant. Due to the - variety of side-channel attacks, many of them only relevant to certain - platforms. In this sense, instead of penalizing all library users with - side-channel countermeasures such as increasing the overall code size, - TinyCrypt only implements certain generic timing-attack countermeasures. - -Specific Remarks -**************** - -* SHA-256: - - * The number of bits_hashed in the state is not checked for overflow. Note - however that this will only be a problem if you intend to hash more than - 2^64 bits, which is an extremely large window. - -* HMAC: - - * The HMAC verification process is assumed to be performed by the application. - This compares the computed tag with some given tag. - Note that conventional memory-comparison methods (such as memcmp function) - might be vulnerable to timing attacks; thus be sure to use a constant-time - memory comparison function (such as compare_constant_time - function provided in lib/utils.c). - - * The tc_hmac_final function, responsible for computing the message tag, - cleans the state context before exiting. Thus, applications do not need to - clean the TCHmacState_t ctx after calling tc_hmac_final. This should not - be changed in future versions of the library as there are applications - currently relying on this good-practice/feature of TinyCrypt. - -* HMAC-PRNG: - - * Before using HMAC-PRNG, you *must* find an entropy source to produce a seed. - PRNGs only stretch the seed into a seemingly random output of arbitrary - length. The security of the output is exactly equal to the - unpredictability of the seed. - - * NIST SP 800-90A requires three items as seed material in the initialization - step: entropy seed, personalization and a nonce (which is not implemented). - TinyCrypt requires the personalization byte array and automatically creates - the entropy seed using a mandatory call to the re-seed function. - -* AES-128: - - * The current implementation does not support other key-lengths (such as 256 - bits). Note that if you need AES-256, it doesn't sound as though your - application is running in a constrained environment. AES-256 requires keys - twice the size as for AES-128, and the key schedule is 40% larger. - -* CTR mode: - - * The AES-CTR mode limits the size of a data message they encrypt to 2^32 - blocks. If you need to encrypt larger data sets, your application would - need to replace the key after 2^32 block encryptions. - -* CTR-PRNG: - - * Before using CTR-PRNG, you *must* find an entropy source to produce a seed. - PRNGs only stretch the seed into a seemingly random output of arbitrary - length. The security of the output is exactly equal to the - unpredictability of the seed. - -* CBC mode: - - * TinyCrypt CBC decryption assumes that the iv and the ciphertext are - contiguous (as produced by TinyCrypt CBC encryption). This allows for a - very efficient decryption algorithm that would not otherwise be possible. - -* CMAC mode: - - * AES128-CMAC mode of operation offers 64 bits of security against collision - attacks. Note however that an external attacker cannot generate the tags - him/herself without knowing the MAC key. In this sense, to attack the - collision property of AES128-CMAC, an external attacker would need the - cooperation of the legal user to produce an exponentially high number of - tags (e.g. 2^64) to finally be able to look for collisions and benefit - from them. As an extra precaution, the current implementation allows to at - most 2^48 calls to tc_cmac_update function before re-calling tc_cmac_setup - (allowing a new key to be set), as suggested in Appendix B of SP 800-38B. - -* CCM mode: - - * There are a few tradeoffs for the selection of the parameters of CCM mode. - In special, there is a tradeoff between the maximum number of invocations - of CCM under a given key and the maximum payload length for those - invocations. Both things are related to the parameter 'q' of CCM mode. The - maximum number of invocations of CCM under a given key is determined by - the nonce size, which is: 15-q bytes. The maximum payload length for those - invocations is defined as 2^(8q) bytes. - - To achieve minimal code size, TinyCrypt CCM implementation fixes q = 2, - which is a quite reasonable choice for constrained applications. The - implications of this choice are: - - The nonce size is: 13 bytes. - - The maximum payload length is: 2^16 bytes = 65 KB. - - The mac size parameter is an important parameter to estimate the security - against collision attacks (that aim at finding different messages that - produce the same authentication tag). TinyCrypt CCM implementation - accepts any even integer between 4 and 16, as suggested in SP 800-38C. - - * TinyCrypt CCM implementation accepts associated data of any length between - 0 and (2^16 - 2^8) = 65280 bytes. - - * TinyCrypt CCM implementation accepts: - - * Both non-empty payload and associated data (it encrypts and - authenticates the payload and only authenticates the associated data); - - * Non-empty payload and empty associated data (it encrypts and - authenticates the payload); - - * Non-empty associated data and empty payload (it degenerates to an - authentication-only mode on the associated data). - - * RFC-3610, which also specifies CCM, presents a few relevant security - suggestions, such as: it is recommended for most applications to use a - mac size greater than 8. Besides, it is emphasized that the usage of the - same nonce for two different messages which are encrypted with the same - key obviously destroys the security properties of CCM mode. - -* ECC-DH and ECC-DSA: - - * TinyCrypt ECC implementation is based on micro-ecc (see - https://github.com/kmackay/micro-ecc). In the original micro-ecc - documentation, there is an important remark about the way integers are - represented: - - "Integer representation: To reduce code size, all large integers are - represented using little-endian words - so the least significant word is - first. You can use the 'ecc_bytes2native()' and 'ecc_native2bytes()' - functions to convert between the native integer representation and the - standardized octet representation." - - Note that the assumed bit layout is: {31, 30, ..., 0}, {63, 62, ..., 32}, - {95, 94, ..., 64}, {127, 126, ..., 96} for a very-long-integer (vli) - consisting of 4 unsigned integers (as an example). - - * A cryptographically-secure PRNG function must be set (using uECC_set_rng()) - before calling uECC_make_key() or uECC_sign(). - -Examples of Applications -************************ -It is possible to do useful cryptography with only the given small set of -primitives. With this list of primitives it becomes feasible to support a range -of cryptography usages: - - * Measurement of code, data structures, and other digital artifacts (SHA256); - - * Generate commitments (SHA256); - - * Construct keys (HMAC-SHA256); - - * Extract entropy from strings containing some randomness (HMAC-SHA256); - - * Construct random mappings (HMAC-SHA256); - - * Construct nonces and challenges (HMAC-PRNG, CTR-PRNG); - - * Authenticate using a shared secret (HMAC-SHA256); - - * Create an authenticated, replay-protected session (HMAC-SHA256 + HMAC-PRNG); - - * Authenticated encryption (AES-128 + AES-CCM); - - * Key-exchange (EC-DH); - - * Digital signature (EC-DSA); - -Test Vectors -************ - -The library provides a test program for each cryptographic primitive (see 'test' -folder). Besides illustrating how to use the primitives, these tests evaluate -the correctness of the implementations by checking the results against -well-known publicly validated test vectors. - -For the case of the HMAC-PRNG, due to the necessity of performing an extensive -battery test to produce meaningful conclusions, we suggest the user to evaluate -the unpredictability of the implementation by using the NIST Statistical Test -Suite (see References). - -For the case of the EC-DH and EC-DSA implementations, most of the test vectors -were obtained from the site of the NIST Cryptographic Algorithm Validation -Program (CAVP), see References. - -References -********** - -* `NIST FIPS PUB 180-4 (SHA-256)`_ - -.. _NIST FIPS PUB 180-4 (SHA-256): - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf - -* `NIST FIPS PUB 197 (AES-128)`_ - -.. _NIST FIPS PUB 197 (AES-128): - http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf - -* `NIST SP800-90A (HMAC-PRNG)`_ - -.. _NIST SP800-90A (HMAC-PRNG): - http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf - -* `NIST SP 800-38A (AES-CBC and AES-CTR)`_ - -.. _NIST SP 800-38A (AES-CBC and AES-CTR): - http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - -* `NIST SP 800-38B (AES-CMAC)`_ - -.. _NIST SP 800-38B (AES-CMAC): - http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf - -* `NIST SP 800-38C (AES-CCM)`_ - -.. _NIST SP 800-38C (AES-CCM): - http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf - -* `NIST Statistical Test Suite (useful for testing HMAC-PRNG)`_ - -.. _NIST Statistical Test Suite (useful for testing HMAC-PRNG): - http://csrc.nist.gov/groups/ST/toolkit/rng/documentation_software.html - -* `NIST Cryptographic Algorithm Validation Program (CAVP) site`_ - -.. _NIST Cryptographic Algorithm Validation Program (CAVP) site: - http://csrc.nist.gov/groups/STM/cavp/ - -* `RFC 2104 (HMAC-SHA256)`_ - -.. _RFC 2104 (HMAC-SHA256): - https://www.ietf.org/rfc/rfc2104.txt - -* `RFC 6090 (ECC-DH and ECC-DSA)`_ - -.. _RFC 6090 (ECC-DH and ECC-DSA): - https://www.ietf.org/rfc/rfc6090.txt From 8553e955ecd2e6a0a837fb36c701b87e8fdec182 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 30 Nov 2021 22:06:20 +0100 Subject: [PATCH 165/185] NimBLE v.1.3.3 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc66c661a..9ac416880 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,9 +10,11 @@ All notable changes to this project will be documented in this file. ### Changed - (Internal) Range conversion edge values +- NimBLE to v.1.3.3 ### Fixed - Tuya dimmer range issue (#13849) +- BLE Memory leak with update NimBLE v.1.3.1 to v.1.3.3 ## [10.0.0.3] 20211130 ### Added From 229b772d99f8779d447c2694fca1139b09789437 Mon Sep 17 00:00:00 2001 From: pkkrusty <79770016+pkkrusty@users.noreply.github.com> Date: Tue, 30 Nov 2021 14:05:40 -0800 Subject: [PATCH 166/185] Changed log level of NRG: EnergyTotal to Level 4 vs Level 3 With console log set to level 3, this function prints out the EnergyTotal every second, which makes the console pretty useless for any other debugging work. Makes more sense to me to have it output all that on Level 4. Still accessible if people want it, but less obtrusive for normal debugging work. --- tasmota/xdrv_03_energy.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_03_energy.ino b/tasmota/xdrv_03_energy.ino index 1a71d5adb..161681e14 100644 --- a/tasmota/xdrv_03_energy.ino +++ b/tasmota/xdrv_03_energy.ino @@ -249,7 +249,7 @@ void EnergyUpdateTotal(void) { // Provide total import active energy as float Energy.import_active[phase] in kWh: 98Wh = 0.098kWh for (uint32_t i = 0; i < Energy.phase_count; i++) { - AddLog(LOG_LEVEL_DEBUG, PSTR("NRG: EnergyTotal[%d] %4_f kWh"), i, &Energy.import_active[i]); + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("NRG: EnergyTotal[%d] %4_f kWh"), i, &Energy.import_active[i]); if (0 == Energy.start_energy[i] || (Energy.import_active[i] < Energy.start_energy[i])) { Energy.start_energy[i] = Energy.import_active[i]; // Init after restart and handle roll-over if any From 5d60365dfbe4cbb285e534bb703b9a242bd2e0f1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 1 Dec 2021 11:21:56 +0100 Subject: [PATCH 167/185] Formalize USE_SONOFF_SPM --- tasmota/my_user_config.h | 5 +++++ tasmota/support_features.ino | 4 +++- tools/decode-status.py | 4 ++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 923e19108..6ffc7c2de 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -968,6 +968,11 @@ #ifdef ESP32 +//#define USE_SONOFF_SPM // Add support for ESP32 based Sonoff Smart Stackable Power Meter(+6k3 code) +#ifdef USE_SONOFF_SPM +#define USE_ETHERNET +#endif + //#define USE_ETHERNET // Add support for ethernet (Currently fixed for Olimex ESP32-PoE) // #define USE_WT32_ETH01 // Add support for Wireless-Tag WT32-ETH01 // #define ETH_TYPE 0 // [EthType] 0 = ETH_PHY_LAN8720, 1 = ETH_PHY_TLK110/ETH_PHY_IP101, 2 = ETH_PHY_RTL8201, 3 = ETH_PHY_DP83848, 4 = ETH_PHY_DM9051, 5 = ETH_PHY_KSZ8081 diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino index 59d12e666..0372c80c8 100644 --- a/tasmota/support_features.ino +++ b/tasmota/support_features.ino @@ -781,7 +781,9 @@ void ResponseAppendFeatures(void) #if defined(USE_LIGHT) && defined(USE_LSC_MCSL) feature8 |= 0x00020000; // xlgt_07_lsc_mcsl.ino #endif -// feature8 |= 0x00040000; +#ifdef USE_SONOFF_SPM + feature8 |= 0x00040000; +#endif // feature8 |= 0x00080000; // feature8 |= 0x00100000; diff --git a/tools/decode-status.py b/tools/decode-status.py index 1ca16c0ab..6e70d8912 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -260,7 +260,7 @@ a_features = [[ "USE_BM8563","USE_ENERGY_DUMMY","USE_AM2320","USE_T67XX", "USE_MCP2515","USE_TASMESH","USE_WIFI_RANGE_EXTENDER","USE_INFLUXDB", "USE_HRG15","USE_VINDRIKTNING","USE_SCD40","USE_HM330X", - "USE_HDC2010","USE_LSC_MCSL","","", + "USE_HDC2010","USE_LSC_MCSL","USE_SONOFF_SPM","", "","","","", "","","","", "","","","" @@ -291,7 +291,7 @@ else: obj = json.load(fp) def StartDecode(): - print ("\n*** decode-status.py v20211130 by Theo Arends and Jacek Ziolkowski ***") + print ("\n*** decode-status.py v20211201 by Theo Arends and Jacek Ziolkowski ***") # print("Decoding\n{}".format(obj)) From 188d6c86c1781b0ca113cca0e4d2d369264356f1 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Wed, 1 Dec 2021 13:52:48 +0100 Subject: [PATCH 168/185] Improve set_power_handler --- tasmota/xdrv_52_3_berry_tasmota.ino | 15 +++++++++++++-- tasmota/xdrv_52_9_berry.ino | 6 +++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/tasmota/xdrv_52_3_berry_tasmota.ino b/tasmota/xdrv_52_3_berry_tasmota.ino index 83de43424..ee65d27a1 100644 --- a/tasmota/xdrv_52_3_berry_tasmota.ino +++ b/tasmota/xdrv_52_3_berry_tasmota.ino @@ -92,6 +92,7 @@ extern "C" { retain = be_tobool(vm, 4); } if (!payload) { be_raise(vm, "value_error", "Empty payload"); } + be_pop(vm, be_top(vm)); MqttPublishPayload(topic, payload, payload_len, retain); be_return_nil(vm); // Return } @@ -122,7 +123,7 @@ extern "C" { int32_t top = be_top(vm); // Get the number of arguments if (top == 2 && be_isstring(vm, 2)) { // only 1 argument of type string accepted const char * command = be_tostring(vm, 2); - be_pop(vm, 2); // clear the stack before calling, because of re-entrant call to Berry in a Rule + be_pop(vm, top); // clear the stack before calling, because of re-entrant call to Berry in a Rule ExecuteCommand(command, SRC_BERRY); be_return_nil(vm); // Return } @@ -390,6 +391,7 @@ extern "C" { int32_t top = be_top(vm); // Get the number of arguments if (top == 2 && be_isstring(vm, 2)) { const char *msg = be_tostring(vm, 2); + be_pop(vm, top); // avoid Error be_top is non zero message ResponseAppend_P(PSTR("%s"), msg); be_return_nil(vm); // Return nil when something goes wrong } @@ -402,6 +404,7 @@ extern "C" { int32_t top = be_top(vm); // Get the number of arguments if (top == 2 && be_isstring(vm, 2)) { const char *msg = be_tostring(vm, 2); + be_pop(vm, top); // avoid Error be_top is non zero message WSContentSend_P(PSTR("%s"), msg); be_return_nil(vm); // Return nil when something goes wrong } @@ -414,6 +417,7 @@ extern "C" { int32_t top = be_top(vm); // Get the number of arguments if (top == 2 && be_isstring(vm, 2)) { const char *msg = be_tostring(vm, 2); + be_pop(vm, top); // avoid Error be_top is non zero message WSContentSend_PD(PSTR("%s"), msg); be_return_nil(vm); // Return nil when something goes wrong } @@ -423,9 +427,14 @@ extern "C" { // get power int32_t l_getpower(bvm *vm); int32_t l_getpower(bvm *vm) { + power_t pow = TasmotaGlobal.power; + int32_t top = be_top(vm); // Get the number of arguments + if (top == 2 && be_isint(vm, 2)) { + pow = be_toint(vm, 2); + } be_newobject(vm, "list"); for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { - be_pushbool(vm, bitRead(TasmotaGlobal.power, i)); + be_pushbool(vm, bitRead(pow, i)); be_data_push(vm, -2); be_pop(vm, 1); } @@ -440,6 +449,7 @@ extern "C" { int32_t idx = be_toint(vm, 2); bool power = be_tobool(vm, 3); if ((idx >= 0) && (idx < TasmotaGlobal.devices_present)) { + be_pop(vm, top); // avoid Error be_top is non zero message ExecuteCommandPower(idx + 1, (power) ? POWER_ON : POWER_OFF, SRC_BERRY); be_pushbool(vm, power); be_return(vm); // Return @@ -473,6 +483,7 @@ extern "C" { int32_t top = be_top(vm); // Get the number of arguments if (top == 2 && be_isint(vm, 2)) { int32_t index = be_toint(vm, 2); + be_pop(vm, top); // avoid Error be_top is non zero message bool enabled = I2cEnabled(index); be_pushbool(vm, enabled); be_return(vm); // Return diff --git a/tasmota/xdrv_52_9_berry.ino b/tasmota/xdrv_52_9_berry.ino index bee52522e..6596782c1 100644 --- a/tasmota/xdrv_52_9_berry.ino +++ b/tasmota/xdrv_52_9_berry.ino @@ -214,7 +214,7 @@ int32_t callBerryEventDispatcher(const char *type, const char *cmd, int32_t idx, be_pushstring(vm, type != nullptr ? type : ""); be_pushstring(vm, cmd != nullptr ? cmd : ""); be_pushint(vm, idx); - be_pushstring(vm, payload != nullptr ? payload : "{}"); // empty json + be_pushstring(vm, payload != nullptr ? payload : ""); // empty json BrTimeoutStart(); if (data_len > 0) { be_pushbytes(vm, payload, data_len); // if data_len is set, we also push raw bytes @@ -811,8 +811,8 @@ bool Xdrv52(uint8_t function) case FUNC_EVERY_SECOND: callBerryEventDispatcher(PSTR("every_second"), nullptr, 0, nullptr); break; - case FUNC_SET_POWER: - callBerryEventDispatcher(PSTR("set_power_handler"), nullptr, XdrvMailbox.index, nullptr); + case FUNC_SET_DEVICE_POWER: + result = callBerryEventDispatcher(PSTR("set_power_handler"), nullptr, XdrvMailbox.index, nullptr); break; #ifdef USE_WEBSERVER case FUNC_WEB_ADD_CONSOLE_BUTTON: From 16e83d1430d3f4f2ed6bc467ffeebf5d1aacab7b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 1 Dec 2021 16:05:03 +0100 Subject: [PATCH 169/185] Fix LSC MC template --- tasmota/xlgt_07_lsc_mcsl.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tasmota/xlgt_07_lsc_mcsl.ino b/tasmota/xlgt_07_lsc_mcsl.ino index 4f71c866f..9e8ec00e6 100644 --- a/tasmota/xlgt_07_lsc_mcsl.ino +++ b/tasmota/xlgt_07_lsc_mcsl.ino @@ -24,7 +24,8 @@ * GP-SW084-052 uses an ESP8285 (TYWE2S) and submicrocontroller controlling two wire RGB leds * https://www.gp-electronic.com/product/integrated-switching-power-supply-with-built-in-controller/eugs/european-vertical-6w8-function.html * - * {"NAME":"LSC MC Lights","GPIO":[1,1,1,1,544,32,1,1,3840,1,3872,1,1,1],"FLAG":0,"BASE":18} + * Template: + * {"NAME":"LSC MC Lights","GPIO":[0,0,0,0,544,32,0,0,3840,0,3872,0,0,0],"FLAG":0,"BASE":18} * * NL: Action LSC Multi color smart lights * From aab4dcdb6abbf9dfb26d345cf27202352e2ed835 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 1 Dec 2021 18:07:13 +0100 Subject: [PATCH 170/185] CI only for branch development prevent CI runs in associated Tasmota helper repos --- .github/workflows/build_all_the_things.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build_all_the_things.yml b/.github/workflows/build_all_the_things.yml index 41629dbab..2ffca53b7 100644 --- a/.github/workflows/build_all_the_things.yml +++ b/.github/workflows/build_all_the_things.yml @@ -3,6 +3,7 @@ name: Tasmota CI on: workflow_dispatch: pull_request: + branches: development paths: - '**.c' - '**.cpp' From b4093770686ab892b635f6382a875764280cf5c9 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Wed, 1 Dec 2021 21:38:28 +0100 Subject: [PATCH 171/185] MQTT TLS dual mode (CA or fingeprint) in same firmware, ``SetOption132 1`` to force fingerprint --- BUILDS.md | 1 - CHANGELOG.md | 1 + lib/lib_ssl/tls_mini/src/StackThunk_light.cpp | 4 +- .../src/WiFiClientSecureLightBearSSL.cpp | 25 +----- tasmota/i18n.h | 1 + tasmota/my_user_config.h | 10 +-- tasmota/settings.h | 2 +- tasmota/settings.ino | 8 ++ tasmota/support_command.ino | 3 + tasmota/tasmota_ca.ino | 4 +- tasmota/tasmota_configurations.h | 3 - tasmota/xdrv_02_9_mqtt.ino | 85 +++++++++---------- tasmota/xdrv_40_telegram.ino | 21 ++--- 13 files changed, 73 insertions(+), 95 deletions(-) diff --git a/BUILDS.md b/BUILDS.md index 228de677f..975e34d24 100644 --- a/BUILDS.md +++ b/BUILDS.md @@ -14,7 +14,6 @@ Note: `minimal` variant is not listed as it shouldn't be used outside of the [up | USE_DOMOTICZ | - | x / x | x | x | x | - | | USE_HOME_ASSISTANT | - | x / x | x | x | x | - | | USE_MQTT_TLS | - | - / - | - | - | - | - | -| USE_MQTT_TLS_CA_CERT | - | - / - | - | - | - | - | | USE_MQTT_AWS_IOT | - | - / - | - | - | - | - | | USE_4K_RSA | - | - / - | - | - | - | - | | USE_TELEGRAM | - | - / - | - | - | - | - | diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ac416880..eb781e0d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file. ### Changed - (Internal) Range conversion edge values - NimBLE to v.1.3.3 +- MQTT TLS dual mode (CA or fingeprint) in same firmware, ``SetOption132 1`` to force fingerprint ### Fixed - Tuya dimmer range issue (#13849) diff --git a/lib/lib_ssl/tls_mini/src/StackThunk_light.cpp b/lib/lib_ssl/tls_mini/src/StackThunk_light.cpp index 70c705e6e..f41c8df59 100644 --- a/lib/lib_ssl/tls_mini/src/StackThunk_light.cpp +++ b/lib/lib_ssl/tls_mini/src/StackThunk_light.cpp @@ -43,10 +43,8 @@ uint32_t stack_thunk_light_refcnt = 0; //#define _stackSize (5600/4) #if defined(USE_MQTT_AWS_IOT) || defined(USE_MQTT_AWS_IOT_LIGHT) || defined(USE_MQTT_AZURE_IOT) #define _stackSize (5300/4) // using a light version of bearssl we can save 300 bytes -#elif defined(USE_MQTT_TLS_FORCE_EC_CIPHER) || defined(USE_4K_RSA) - #define _stackSize (4800/4) // no private key, we can reduce a little, max observed 4300 #else - #define _stackSize (3800/4) // using a light version of bearssl we can save 2k + #define _stackSize (4800/4) // no private key, we can reduce a little, max observed 4300 #endif #define _stackPaint 0xdeadbeef diff --git a/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.cpp b/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.cpp index 6f66915f3..7be46adf0 100755 --- a/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.cpp +++ b/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.cpp @@ -191,11 +191,7 @@ void WiFiClientSecure_light::_clear() { _last_error = 0; _recvapp_buf = nullptr; _recvapp_len = 0; -#ifdef USE_MQTT_TLS_CA_CERT - _insecure = false; // insecure (fingerprint) mode is only enabled if setPubKeyFingerprint() is called -#else - _insecure = true; // force insecure if CA validation is not enabled -#endif + _insecure = false; // set to true when calling setPubKeyFingerprint() _fingerprint_any = true; // by default accept all fingerprints _fingerprint1 = nullptr; _fingerprint2 = nullptr; @@ -920,11 +916,7 @@ extern "C" { // We limit to a single cipher to reduce footprint // we reference it, don't put in PROGMEM static const uint16_t suites[] = { -#ifdef USE_MQTT_TLS_FORCE_EC_CIPHER BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 -#else - BR_TLS_RSA_WITH_AES_128_GCM_SHA256 -#endif }; // Default initializion for our SSL clients @@ -947,10 +939,8 @@ extern "C" { br_ssl_engine_set_aes_ctr(&cc->eng, &br_aes_small_ctr_vtable); br_ssl_engine_set_ghash(&cc->eng, &br_ghash_ctmul32); -#ifdef USE_MQTT_TLS_FORCE_EC_CIPHER // we support only P256 EC curve for AWS IoT, no EC curve for Letsencrypt unless forced br_ssl_engine_set_ec(&cc->eng, &br_ec_p256_m15); // TODO -#endif } } @@ -958,9 +948,8 @@ extern "C" { // Returns if the SSL handshake succeeded. bool WiFiClientSecure_light::_connectSSL(const char* hostName) { // Validation context, either full CA validation or checking only fingerprints -#ifdef USE_MQTT_TLS_CA_CERT + br_x509_minimal_context *x509_minimal = nullptr; -#endif br_x509_pubkeyfingerprint_context *x509_insecure = nullptr; LOG_HEAP_SIZE("_connectSSL.start"); @@ -998,7 +987,6 @@ bool WiFiClientSecure_light::_connectSSL(const char* hostName) { br_x509_pubkeyfingerprint_init(x509_insecure, _fingerprint1, _fingerprint2, _recv_fingerprint, _fingerprint_any); br_ssl_engine_set_x509(_eng, &x509_insecure->vtable); - #ifdef USE_MQTT_TLS_CA_CERT if (!_insecure) { x509_minimal = (br_x509_minimal_context*) malloc(sizeof(br_x509_minimal_context)); if (!x509_minimal) break; @@ -1011,7 +999,6 @@ bool WiFiClientSecure_light::_connectSSL(const char* hostName) { if (cfg_time > now) { now = cfg_time; } br_x509_minimal_set_time(x509_minimal, now / 86400 + 719528, now % 86400); } - #endif LOG_HEAP_SIZE("_connectSSL after DecoderContext allocation"); // ============================================================ @@ -1050,9 +1037,7 @@ bool WiFiClientSecure_light::_connectSSL(const char* hostName) { LOG_HEAP_SIZE("_connectSSL.end, freeing StackThunk"); #endif // ESP8266 - #ifdef USE_MQTT_TLS_CA_CERT - free(x509_minimal); - #endif + free(x509_minimal); // safe to call if nullptr free(x509_insecure); LOG_HEAP_SIZE("_connectSSL after release of Priv Key"); return ret; @@ -1065,9 +1050,7 @@ bool WiFiClientSecure_light::_connectSSL(const char* hostName) { #ifdef ESP8266 stack_thunk_light_del_ref(); #endif -#ifdef USE_MQTT_TLS_CA_CERT - free(x509_minimal); -#endif + free(x509_minimal); // safe to call if nullptr free(x509_insecure); LOG_HEAP_SIZE("_connectSSL clean_on_error"); return false; diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 2e31ff08d..462774a53 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -371,6 +371,7 @@ // Commands xdrv_02_mqtt.ino #define D_SO_MQTTJSONONLY "MqttJSONOnly" #define D_SO_MQTTTLS "MqttTLS" +#define D_SO_MQTTTLS_FINGERPRINT "MqttTLSFingerprint" #define D_SO_MQTTNORETAIN "MqttNoRetain" #define D_SO_MQTTDETACHRELAY "MqttDetachRelay" #define D_CMND_MQTTLOG "MqttLog" diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 6ffc7c2de..f04b79d93 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -170,6 +170,7 @@ #define MQTT_INDEX_SEPARATOR false // [SetOption64] Enable "_" instead of "-" as sensor index separator #define MQTT_TUYA_RECEIVED false // [SetOption66] Enable TuyaMcuReceived messages over Mqtt #define MQTT_TLS_ENABLED false // [SetOption103] Enable TLS mode (requires TLS version) +#define MQTT_TLS_FINGERPRINT false // [SetOption132] Force TLS fingerprint validation instead of CA (requires TLS version) // -- HTTP ---------------------------------------- #define WEB_SERVER 2 // [WebServer] Web server (0 = Off, 1 = Start as User, 2 = Start as Admin) @@ -430,9 +431,7 @@ // -- MQTT - TLS - AWS IoT ------------------------ // Using TLS starting with version v6.5.0.16 compilation will only work using Core 2.4.2 and 2.5.2. No longer supported: 2.3.0 //#define USE_MQTT_TLS // Use TLS for MQTT connection (+34.5k code, +7.0k mem and +4.8k additional during connection handshake) -// #define USE_MQTT_TLS_CA_CERT // Force full CA validation instead of fingerprints, slower, but simpler to use. (+2.2k code, +1.9k mem during connection handshake) - // This includes the LetsEncrypt CA in tasmota_ca.ino for verifying server certificates -// #define USE_MQTT_TLS_FORCE_EC_CIPHER // Force Elliptic Curve cipher (higher security) required by some servers (automatically enabled with USE_MQTT_AWS_IOT) (+11.4k code, +0.4k mem) +// #define USE_MQTT_TLS_CA_CERT // [DEPRECATED] Now TLS supports dual mode using SetOption132 - this flag is now ignored // #define USE_MQTT_AWS_IOT_LIGHT // Enable MQTT for AWS IoT in light mode, with user/password instead of private certificate // #define USE_MQTT_AWS_IOT // [Deprecated] Enable MQTT for AWS IoT - requires a private key (+11.9k code, +0.4k mem) // Note: you need to generate a private key + certificate per device and update 'tasmota/tasmota_aws_iot.cpp' @@ -453,7 +452,6 @@ // -- Telegram Protocol --------------------------- //#define USE_TELEGRAM // Support for Telegram protocol (+49k code, +7.0k mem and +4.8k additional during connection handshake) #define USE_TELEGRAM_FINGERPRINT "\xB2\x72\x47\xA6\x69\x8C\x3C\x69\xF9\x58\x6C\xF3\x60\x02\xFB\x83\xFA\x8B\x1F\x23" // Telegram api.telegram.org TLS public key fingerpring -// #define USE_MQTT_TLS_CA_CERT // Use certificate instead of fingerprint // -- KNX IP Protocol ----------------------------- //#define USE_KNX // Enable KNX IP Protocol Support (+9.4k code, +3k7 mem) @@ -1117,10 +1115,6 @@ #if defined(USE_MQTT_TLS) || defined(USE_SENDMAIL) || defined(USE_TELEGRAM) || defined(USE_WEBCLIENT_HTTPS) || defined(USE_ALEXA_AVS) #define USE_TLS // flag indicates we need to include TLS code - - #if defined(USE_MQTT_AWS_IOT) || defined(USE_TELEGRAM) || defined(USE_WEBCLIENT_HTTPS) - #define USE_MQTT_TLS_FORCE_EC_CIPHER // AWS IoT and TELEGRAM require EC Cipher - #endif #endif #endif // _MY_USER_CONFIG_H_ diff --git a/tasmota/settings.h b/tasmota/settings.h index b168422fc..3686b1d42 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -161,7 +161,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t energy_phase : 1; // bit 15 (v9.5.0.9) - SetOption129 - (Energy) Show phase information uint32_t show_heap_with_timestamp : 1; // bit 16 (v9.5.0.9) - SetOption130 - (Debug) Show heap with logging timestamp uint32_t tuya_allow_dimmer_0 : 1; // bit 17 (v10.0.0.3) - SetOption131 - (Tuya) Allow save dimmer = 0 receved by MCU - uint32_t spare18 : 1; // bit 18 + uint32_t tls_use_fingerprint : 1; // bit 18 (v10.0.0.4) - SetOption132 - (TLS) use fingerprint validation instead of CA based uint32_t spare19 : 1; // bit 19 uint32_t spare20 : 1; // bit 20 uint32_t spare21 : 1; // bit 21 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index bab1870db..faee15800 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -1458,6 +1458,14 @@ void SettingsDelta(void) { if (Settings->version < 0x0A000003) { if (0 == Settings->param[P_ARP_GRATUITOUS]) { Settings->param[P_ARP_GRATUITOUS] = WIFI_ARP_INTERVAL; +#ifdef USE_TLS + for (uint32_t i = 0; i < 20; i++) { + if (Settings->mqtt_fingerprint[0][i]) { + Settings->flag5.tls_use_fingerprint = true; // if the fingerprint1 is non null we expect it to be actually used + break; + } + } +#endif } } diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 23cd04c0b..a467f2de1 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -1068,6 +1068,9 @@ void CmndSetoptionBase(bool indexed) { TasmotaGlobal.restart_flag = 2; } break; + case 18: // SetOption132 - TLS Fingerprint + TasmotaGlobal.restart_flag = 2; + break; } } } else { diff --git a/tasmota/tasmota_ca.ino b/tasmota/tasmota_ca.ino index 90a90d961..e77ce541d 100644 --- a/tasmota/tasmota_ca.ino +++ b/tasmota/tasmota_ca.ino @@ -21,7 +21,7 @@ // Please use fingerprint validation instead // However, the CA are available below for future use if it appears to be useful -#if defined(USE_TLS) && defined(USE_MQTT_TLS_CA_CERT) +#if defined(USE_TLS) /*********************************************************************************************\ * LetsEncrypt R3 certificate, RSA 2048 bits SHA 256, valid until 20250915 @@ -232,4 +232,4 @@ const br_x509_trust_anchor GoDaddyCAG2_TA PROGMEM = { } }; -#endif // defined(USE_TLS) && defined(USE_MQTT_TLS_CA_CERT) +#endif // defined(USE_TLS) diff --git a/tasmota/tasmota_configurations.h b/tasmota/tasmota_configurations.h index 8dc302dad..7a417e787 100644 --- a/tasmota/tasmota_configurations.h +++ b/tasmota/tasmota_configurations.h @@ -497,9 +497,6 @@ // -- MQTT - TLS - AWS IoT ------------------------ #ifdef USE_ZBBRIDGE_TLS // Enable TLS for ZbBridge #define USE_MQTT_TLS // Use TLS for MQTT connection (+34.5k code, +7.0k mem and +4.8k additional during connection handshake) - #define USE_MQTT_TLS_CA_CERT // Force full CA validation instead of fingerprints, slower, but simpler to use. (+2.2k code, +1.9k mem during connection handshake) - // This includes the LetsEncrypt CA in tasmota_ca.ino for verifying server certificates - #define USE_MQTT_TLS_FORCE_EC_CIPHER // Force Elliptic Curve cipher (higher security) required by some servers (automatically enabled with USE_MQTT_AWS_IOT) (+11.4k code, +0.4k mem) #define USE_MQTT_AWS_IOT_LIGHT // Enable MQTT for AWS IoT in light mode, with user/password instead of private certificate #define USE_TLS // flag indicates we need to include TLS code #endif // USE_ZBBRIDGE_TLS diff --git a/tasmota/xdrv_02_9_mqtt.ino b/tasmota/xdrv_02_9_mqtt.ino index f5302330f..0b02b629d 100644 --- a/tasmota/xdrv_02_9_mqtt.ino +++ b/tasmota/xdrv_02_9_mqtt.ino @@ -48,11 +48,11 @@ const char kMqttCommands[] PROGMEM = "|" // No prefix // SetOption synonyms D_SO_MQTTJSONONLY "|" #ifdef USE_MQTT_TLS - D_SO_MQTTTLS "|" + D_SO_MQTTTLS "|" D_SO_MQTTTLS_FINGERPRINT "|" #endif D_SO_MQTTNORETAIN "|" D_SO_MQTTDETACHRELAY "|" // regular commands -#if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT) +#if defined(USE_MQTT_TLS) D_CMND_MQTTFINGERPRINT "|" #endif D_CMND_MQTTUSER "|" D_CMND_MQTTPASSWORD "|" D_CMND_MQTTKEEPALIVE "|" D_CMND_MQTTTIMEOUT "|" D_CMND_MQTTWIFITIMEOUT "|" @@ -70,18 +70,13 @@ const char kMqttCommands[] PROGMEM = "|" // No prefix SO_SYNONYMS(kMqttSynonyms, 90, #ifdef USE_MQTT_TLS - 103, + 103, 132, #endif 104, 114 ); -// const uint8_t kMqttSynonyms[] PROGMEM = { -// 4, // number of synonyms -// 90, 103, 104, 114, -// }; - void (* const MqttCommand[])(void) PROGMEM = { -#if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT) +#if defined(USE_MQTT_TLS) &CmndMqttFingerprint, #endif &CmndMqttUser, &CmndMqttPassword, &CmndMqttKeepAlive, &CmndMqttTimeout, &CmndMqttWifiTimeout, @@ -231,9 +226,9 @@ void MqttInit(void) { } #endif -#ifdef USE_MQTT_TLS_CA_CERT - tlsClient->setTrustAnchor(Tasmota_TA, nitems(Tasmota_TA)); -#endif // USE_MQTT_TLS_CA_CERT + if (!Settings->flag5.tls_use_fingerprint) { + tlsClient->setTrustAnchor(Tasmota_TA, nitems(Tasmota_TA)); + } MqttClient.setClient(*tlsClient); } else { @@ -953,7 +948,7 @@ void MqttConnected(void) { void MqttReconnect(void) { char stopic[TOPSZ]; - Mqtt.allowed = Settings->flag.mqtt_enabled; // SetOption3 - Enable MQTT + Mqtt.allowed = Settings->flag.mqtt_enabled && (TasmotaGlobal.restart_flag == 0); // SetOption3 - Enable MQTT, and don't connect if restart in process if (Mqtt.allowed) { #if defined(USE_MQTT_AZURE_DPS_SCOPEID) && defined(USE_MQTT_AZURE_DPS_PRESHAREDKEY) ProvisionAzureDPS(); @@ -1043,11 +1038,11 @@ void MqttReconnect(void) { MqttClient.setServer(SettingsText(SET_MQTT_HOST), Settings->mqtt_port); uint32_t mqtt_connect_time = millis(); -#if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT) - bool allow_all_fingerprints; - bool learn_fingerprint1; - bool learn_fingerprint2; - if (Mqtt.mqtt_tls) { +#if defined(USE_MQTT_TLS) + bool allow_all_fingerprints = false; + bool learn_fingerprint1 = false; + bool learn_fingerprint2 = false; + if (Mqtt.mqtt_tls && Settings->flag5.tls_use_fingerprint) { allow_all_fingerprints = false; learn_fingerprint1 = is_fingerprint_mono_value(Settings->mqtt_fingerprint[0], 0x00); learn_fingerprint2 = is_fingerprint_mono_value(Settings->mqtt_fingerprint[1], 0x00); @@ -1094,35 +1089,37 @@ void MqttReconnect(void) { if (!tlsClient->getMFLNStatus()) { AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "MFLN not supported by TLS server")); } -#ifndef USE_MQTT_TLS_CA_CERT // don't bother with fingerprints if using CA validation - const uint8_t *recv_fingerprint = tlsClient->getRecvPubKeyFingerprint(); - // create a printable version of the fingerprint received - char buf_fingerprint[64]; - ToHex_P(recv_fingerprint, 20, buf_fingerprint, sizeof(buf_fingerprint), ' '); - AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT "Server fingerprint: %s"), buf_fingerprint); - bool learned = false; + if (Settings->flag5.tls_use_fingerprint) { // CA validation + const uint8_t *recv_fingerprint = tlsClient->getRecvPubKeyFingerprint(); + // create a printable version of the fingerprint received + char buf_fingerprint[64]; + ToHex_P(recv_fingerprint, 20, buf_fingerprint, sizeof(buf_fingerprint), ' '); + AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT "Server fingerprint: %s"), buf_fingerprint); - // If the fingerprint slot is marked for update, we'll do so. - // Otherwise, if the fingerprint slot had the magic trust-on-first-use - // value, we will save the current fingerprint there, but only if the other fingerprint slot - // *didn't* match it. - if (recv_fingerprint[20] & 0x1 || (learn_fingerprint1 && 0 != memcmp(recv_fingerprint, Settings->mqtt_fingerprint[1], 20))) { - memcpy(Settings->mqtt_fingerprint[0], recv_fingerprint, 20); - learned = true; - } - // As above, but for the other slot. - if (recv_fingerprint[20] & 0x2 || (learn_fingerprint2 && 0 != memcmp(recv_fingerprint, Settings->mqtt_fingerprint[0], 20))) { - memcpy(Settings->mqtt_fingerprint[1], recv_fingerprint, 20); - learned = true; + bool learned = false; + + // If the fingerprint slot is marked for update, we'll do so. + // Otherwise, if the fingerprint slot had the magic trust-on-first-use + // value, we will save the current fingerprint there, but only if the other fingerprint slot + // *didn't* match it. + if (recv_fingerprint[20] & 0x1 || (learn_fingerprint1 && 0 != memcmp(recv_fingerprint, Settings->mqtt_fingerprint[1], 20))) { + memcpy(Settings->mqtt_fingerprint[0], recv_fingerprint, 20); + learned = true; + } + // As above, but for the other slot. + if (recv_fingerprint[20] & 0x2 || (learn_fingerprint2 && 0 != memcmp(recv_fingerprint, Settings->mqtt_fingerprint[0], 20))) { + memcpy(Settings->mqtt_fingerprint[1], recv_fingerprint, 20); + learned = true; + } + + if (learned) { + AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "Fingerprint learned: %s"), buf_fingerprint); + + SettingsSaveAll(); // save settings + } } - if (learned) { - AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "Fingerprint learned: %s"), buf_fingerprint); - - SettingsSaveAll(); // save settings - } -#endif // !USE_MQTT_TLS_CA_CERT } #endif // USE_MQTT_TLS MqttConnected(); @@ -1275,7 +1272,7 @@ bool KeyTopicActive(uint32_t key) { * Commands \*********************************************************************************************/ -#if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT) +#if defined(USE_MQTT_TLS) void CmndMqttFingerprint(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { char fingerprint[60]; diff --git a/tasmota/xdrv_40_telegram.ino b/tasmota/xdrv_40_telegram.ino index f50d14a88..dacd85e0b 100644 --- a/tasmota/xdrv_40_telegram.ino +++ b/tasmota/xdrv_40_telegram.ino @@ -47,13 +47,8 @@ #define TELEGRAM_SEND_RETRY 4 // Retries #define TELEGRAM_MAX_MESSAGES 2 -#ifdef USE_MQTT_TLS_CA_CERT - static const uint32_t tls_rx_size = 2048; // since Telegram CA is bigger than 1024 bytes, we need to increase rx buffer - static const uint32_t tls_tx_size = 1024; -#else - static const uint32_t tls_rx_size = 1024; - static const uint32_t tls_tx_size = 1024; -#endif +static const uint32_t tls_rx_size = 2048; // since Telegram CA is bigger than 1024 bytes, we need to increase rx buffer +static const uint32_t tls_tx_size = 1024; #include "WiFiClientSecureLightBearSSL.h" BearSSL::WiFiClientSecure_light *telegramClient = nullptr; @@ -87,11 +82,13 @@ bool TelegramInit(void) { if (strlen(SettingsText(SET_TELEGRAM_TOKEN))) { if (!telegramClient) { telegramClient = new BearSSL::WiFiClientSecure_light(tls_rx_size, tls_tx_size); -#ifdef USE_MQTT_TLS_CA_CERT - telegramClient->setTrustAnchor(&GoDaddyCAG2_TA, 1); -#else - telegramClient->setPubKeyFingerprint(Telegram_Fingerprint, Telegram_Fingerprint, false); // check server fingerprint -#endif + + if (Settings.flag5.tls_use_fingerprint) { + telegramClient->setPubKeyFingerprint(Telegram_Fingerprint, Telegram_Fingerprint, false); // check server fingerprint + } else { + telegramClient->setTrustAnchor(&GoDaddyCAG2_TA, 1); + } + Telegram.message_count = 0; // Number of received messages Telegram.next_update_id = 0; // Code of last read Message Telegram.message[0].text = ""; From a147e00f6d627eb456ab4a1da7c9c72b7b98ba9a Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Wed, 1 Dec 2021 21:54:00 +0100 Subject: [PATCH 172/185] Berry prevent crash when setting superclass of solidified class --- lib/libesp32/Berry/src/be_vm.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/libesp32/Berry/src/be_vm.c b/lib/libesp32/Berry/src/be_vm.c index f00cc128a..dd60e34b7 100644 --- a/lib/libesp32/Berry/src/be_vm.c +++ b/lib/libesp32/Berry/src/be_vm.c @@ -984,7 +984,12 @@ newframe: /* a new call frame */ bvalue *a = RA(), *b = RKB(); if (var_isclass(a) && var_isclass(b)) { bclass *obj = var_toobj(a); - be_class_setsuper(obj, var_toobj(b)); + if (!gc_isconst(obj)) { + be_class_setsuper(obj, var_toobj(b)); + } else { + vm_error(vm, "internal_error", + "cannot change superclass of a read-only class"); + } } else { vm_error(vm, "type_error", "value '%s' does not support set super", From e98d632e07fd96f32419260df7ddbb4f3b1cdba2 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Wed, 1 Dec 2021 22:41:44 +0100 Subject: [PATCH 173/185] TLS always set ALPN for AWS IoT --- tasmota/xdrv_02_9_mqtt.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tasmota/xdrv_02_9_mqtt.ino b/tasmota/xdrv_02_9_mqtt.ino index 0b02b629d..a1a763b47 100644 --- a/tasmota/xdrv_02_9_mqtt.ino +++ b/tasmota/xdrv_02_9_mqtt.ino @@ -192,6 +192,7 @@ void MqttInit(void) { Settings->mqtt_port = 8883; #endif //USE_MQTT_AZURE_IOT #ifdef USE_MQTT_TLS + bool aws_iot_host = false; if ((8883 == Settings->mqtt_port) || (8884 == Settings->mqtt_port) || (443 == Settings->mqtt_port)) { // Turn on TLS for port 8883 (TLS), 8884 (TLS, client certificate), 443 (TLS, user/password) Settings->flag4.mqtt_tls = true; @@ -202,6 +203,7 @@ void MqttInit(void) { String host = String(SettingsText(SET_MQTT_HOST)); if (host.indexOf(F(".iot.")) && host.endsWith(F(".amazonaws.com"))) { // look for ".iot." and ".amazonaws.com" in the domain name Settings->flag4.mqtt_no_retain = true; + aws_iot_host = true; } if (Mqtt.mqtt_tls) { @@ -211,12 +213,10 @@ void MqttInit(void) { tlsClient = new BearSSL::WiFiClientSecure_light(1024,1024); #endif -#ifdef USE_MQTT_AWS_IOT_LIGHT - if (443 == Settings->mqtt_port) { + if (443 == Settings->mqtt_port && aws_iot_host) { static const char * alpn_mqtt = "mqtt"; // needs to be static tlsClient->setALPN(&alpn_mqtt, 1); // need to set alpn to 'mqtt' for AWS IoT } -#endif #ifdef USE_MQTT_AWS_IOT loadTlsDir(); // load key and certificate data from Flash if ((nullptr != AWS_IoT_Private_Key) && (nullptr != AWS_IoT_Client_Certificate)) { From 5d91392ae8658eac1f1da8579620800f90152003 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Wed, 1 Dec 2021 22:44:58 +0100 Subject: [PATCH 174/185] Berry leds improvements --- lib/libesp32/Berry/default/be_leds_lib.c | 1464 +++++++++++++++-- .../Berry/default/be_leds_matrix_lib.c | 185 --- lib/libesp32/Berry/default/be_leds_ntv_lib.c | 14 +- lib/libesp32/Berry/default/be_modtab.c | 2 - lib/libesp32/Berry/default/embedded/leds.be | 200 ++- tasmota/berry/leds/rainbow.be | 54 +- tasmota/xdrv_52_3_berry_leds.ino | 65 +- 7 files changed, 1535 insertions(+), 449 deletions(-) delete mode 100644 lib/libesp32/Berry/default/be_leds_matrix_lib.c diff --git a/lib/libesp32/Berry/default/be_leds_lib.c b/lib/libesp32/Berry/default/be_leds_lib.c index a4442df37..06e322c13 100644 --- a/lib/libesp32/Berry/default/be_leds_lib.c +++ b/lib/libesp32/Berry/default/be_leds_lib.c @@ -7,11 +7,41 @@ #ifdef USE_WS2812 /******************************************************************** -** Solidified function: get_pixel_color +** Solidified function: pixel_count ********************************************************************/ -be_local_closure(Leds_get_pixel_color, /* name */ +be_local_closure(Leds_matrix_pixel_count, /* name */ be_nested_proto( - 6, /* nstack */ + 3, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_literal("w"), + /* K1 */ be_nested_str_literal("h"), + }), + (be_nested_const_str("pixel_count", -1855836553, 11)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 4]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x88080101, // 0001 GETMBR R2 R0 K1 + 0x08040202, // 0002 MUL R1 R1 R2 + 0x80040200, // 0003 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_alternate +********************************************************************/ +be_local_closure(Leds_matrix_set_alternate, /* name */ + be_nested_proto( + 2, /* nstack */ 2, /* argc */ 0, /* varg */ 0, /* has upvals */ @@ -20,16 +50,13 @@ be_local_closure(Leds_get_pixel_color, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_literal("call_native"), + /* K0 */ be_nested_str_literal("alternate"), }), - (be_nested_const_str("get_pixel_color", 337490048, 15)), + (be_nested_const_str("set_alternate", 1709680562, 13)), ((bstring*) &be_const_str_input), - ( &(const binstruction[ 5]) { /* code */ - 0x8C080100, // 0000 GETMET R2 R0 K0 - 0x5412000A, // 0001 LDINT R4 11 - 0x5C140200, // 0002 MOVE R5 R1 - 0x7C080600, // 0003 CALL R2 3 - 0x80040400, // 0004 RET 1 R2 + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 }) ) ); @@ -37,11 +64,11 @@ be_local_closure(Leds_get_pixel_color, /* name */ /******************************************************************** -** Solidified function: pixels_buffer +** Solidified function: pixel_size ********************************************************************/ -be_local_closure(Leds_pixels_buffer, /* name */ +be_local_closure(Leds_matrix_pixel_size, /* name */ be_nested_proto( - 4, /* nstack */ + 3, /* nstack */ 1, /* argc */ 0, /* varg */ 0, /* has upvals */ @@ -49,15 +76,16 @@ be_local_closure(Leds_pixels_buffer, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_literal("call_native"), + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_literal("strip"), + /* K1 */ be_nested_str_literal("pixel_size"), }), - (be_nested_const_str("pixels_buffer", 1229555807, 13)), + (be_nested_const_str("pixel_size", -2085831511, 10)), ((bstring*) &be_const_str_input), ( &(const binstruction[ 4]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x540E0005, // 0001 LDINT R3 6 - 0x7C040400, // 0002 CALL R1 2 + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x7C040200, // 0002 CALL R1 1 0x80040200, // 0003 RET 1 R1 }) ) @@ -65,10 +93,232 @@ be_local_closure(Leds_pixels_buffer, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: set_pixel_color +********************************************************************/ +be_local_closure(Leds_matrix_set_pixel_color, /* name */ + be_nested_proto( + 9, /* nstack */ + 4, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_literal("strip"), + /* K1 */ be_nested_str_literal("set_pixel_color"), + /* K2 */ be_nested_str_literal("offset"), + }), + (be_nested_const_str("set_pixel_color", 1275248356, 15)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 8]) { /* code */ + 0x88100100, // 0000 GETMBR R4 R0 K0 + 0x8C100901, // 0001 GETMET R4 R4 K1 + 0x88180102, // 0002 GETMBR R6 R0 K2 + 0x00180206, // 0003 ADD R6 R1 R6 + 0x5C1C0400, // 0004 MOVE R7 R2 + 0x5C200600, // 0005 MOVE R8 R3 + 0x7C100800, // 0006 CALL R4 4 + 0x80000000, // 0007 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_matrix_pixel_color +********************************************************************/ +be_local_closure(Leds_matrix_set_matrix_pixel_color, /* name */ + be_nested_proto( + 10, /* nstack */ + 5, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 8]) { /* constants */ + /* K0 */ be_nested_str_literal("alternate"), + /* K1 */ be_const_int(2), + /* K2 */ be_nested_str_literal("strip"), + /* K3 */ be_nested_str_literal("set_pixel_color"), + /* K4 */ be_nested_str_literal("w"), + /* K5 */ be_nested_str_literal("h"), + /* K6 */ be_const_int(1), + /* K7 */ be_nested_str_literal("offset"), + }), + (be_nested_const_str("set_matrix_pixel_color", 1197149462, 22)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[29]) { /* code */ + 0x88140100, // 0000 GETMBR R5 R0 K0 + 0x7816000F, // 0001 JMPF R5 #0012 + 0x10140301, // 0002 MOD R5 R1 K1 + 0x7816000D, // 0003 JMPF R5 #0012 + 0x88140102, // 0004 GETMBR R5 R0 K2 + 0x8C140B03, // 0005 GETMET R5 R5 K3 + 0x881C0104, // 0006 GETMBR R7 R0 K4 + 0x081C0207, // 0007 MUL R7 R1 R7 + 0x88200105, // 0008 GETMBR R8 R0 K5 + 0x001C0E08, // 0009 ADD R7 R7 R8 + 0x041C0E02, // 000A SUB R7 R7 R2 + 0x041C0F06, // 000B SUB R7 R7 K6 + 0x88200107, // 000C GETMBR R8 R0 K7 + 0x001C0E08, // 000D ADD R7 R7 R8 + 0x5C200600, // 000E MOVE R8 R3 + 0x5C240800, // 000F MOVE R9 R4 + 0x7C140800, // 0010 CALL R5 4 + 0x70020009, // 0011 JMP #001C + 0x88140102, // 0012 GETMBR R5 R0 K2 + 0x8C140B03, // 0013 GETMET R5 R5 K3 + 0x881C0104, // 0014 GETMBR R7 R0 K4 + 0x081C0207, // 0015 MUL R7 R1 R7 + 0x001C0E02, // 0016 ADD R7 R7 R2 + 0x88200107, // 0017 GETMBR R8 R0 K7 + 0x001C0E08, // 0018 ADD R7 R7 R8 + 0x5C200600, // 0019 MOVE R8 R3 + 0x5C240800, // 001A MOVE R9 R4 + 0x7C140800, // 001B CALL R5 4 + 0x80000000, // 001C RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: show +********************************************************************/ +be_local_closure(Leds_matrix_show, /* name */ + be_nested_proto( + 4, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 7]) { /* constants */ + /* K0 */ be_nested_str_literal("offset"), + /* K1 */ be_const_int(0), + /* K2 */ be_nested_str_literal("w"), + /* K3 */ be_nested_str_literal("h"), + /* K4 */ be_nested_str_literal("strip"), + /* K5 */ be_nested_str_literal("leds"), + /* K6 */ be_nested_str_literal("show"), + }), + (be_nested_const_str("show", -1454906820, 4)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[18]) { /* code */ + 0x60080017, // 0000 GETGBL R2 G23 + 0x5C0C0200, // 0001 MOVE R3 R1 + 0x7C080200, // 0002 CALL R2 1 + 0x740A0009, // 0003 JMPT R2 #000E + 0x88080100, // 0004 GETMBR R2 R0 K0 + 0x1C080501, // 0005 EQ R2 R2 K1 + 0x780A0009, // 0006 JMPF R2 #0011 + 0x88080102, // 0007 GETMBR R2 R0 K2 + 0x880C0103, // 0008 GETMBR R3 R0 K3 + 0x08080403, // 0009 MUL R2 R2 R3 + 0x880C0104, // 000A GETMBR R3 R0 K4 + 0x880C0705, // 000B GETMBR R3 R3 K5 + 0x1C080403, // 000C EQ R2 R2 R3 + 0x780A0002, // 000D JMPF R2 #0011 + 0x88080104, // 000E GETMBR R2 R0 K4 + 0x8C080506, // 000F GETMET R2 R2 K6 + 0x7C080200, // 0010 CALL R2 1 + 0x80000000, // 0011 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: is_dirty +********************************************************************/ +be_local_closure(Leds_matrix_is_dirty, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_literal("strip"), + /* K1 */ be_nested_str_literal("is_dirty"), + }), + (be_nested_const_str("is_dirty", 418034110, 8)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 4]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x7C040200, // 0002 CALL R1 1 + 0x80040200, // 0003 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: clear_to +********************************************************************/ +be_local_closure(Leds_matrix_clear_to, /* name */ + be_nested_proto( + 9, /* nstack */ + 3, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 7]) { /* constants */ + /* K0 */ be_const_int(0), + /* K1 */ be_nested_str_literal("w"), + /* K2 */ be_nested_str_literal("h"), + /* K3 */ be_nested_str_literal("strip"), + /* K4 */ be_nested_str_literal("set_pixel_color"), + /* K5 */ be_nested_str_literal("offset"), + /* K6 */ be_const_int(1), + }), + (be_nested_const_str("clear_to", -766965166, 8)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[16]) { /* code */ + 0x580C0000, // 0000 LDCONST R3 K0 + 0x88100101, // 0001 GETMBR R4 R0 K1 + 0x88140102, // 0002 GETMBR R5 R0 K2 + 0x08100805, // 0003 MUL R4 R4 R5 + 0x14100604, // 0004 LT R4 R3 R4 + 0x78120008, // 0005 JMPF R4 #000F + 0x88100103, // 0006 GETMBR R4 R0 K3 + 0x8C100904, // 0007 GETMET R4 R4 K4 + 0x88180105, // 0008 GETMBR R6 R0 K5 + 0x00180606, // 0009 ADD R6 R3 R6 + 0x5C1C0200, // 000A MOVE R7 R1 + 0x5C200400, // 000B MOVE R8 R2 + 0x7C100800, // 000C CALL R4 4 + 0x000C0706, // 000D ADD R3 R3 K6 + 0x7001FFF1, // 000E JMP #0001 + 0x80000000, // 000F RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: clear ********************************************************************/ -be_local_closure(Leds_clear, /* name */ +be_local_closure(Leds_matrix_clear, /* name */ be_nested_proto( 4, /* nstack */ 1, /* argc */ @@ -99,66 +349,24 @@ be_local_closure(Leds_clear, /* name */ /******************************************************************** -** Solidified function: init +** Solidified function: pixels_buffer ********************************************************************/ -be_local_closure(Leds_init, /* name */ +be_local_closure(Leds_matrix_pixels_buffer, /* name */ be_nested_proto( - 11, /* nstack */ - 5, /* argc */ + 2, /* nstack */ + 1, /* argc */ 0, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[11]) { /* constants */ - /* K0 */ be_nested_str_literal("gamma"), - /* K1 */ be_nested_str_literal("pin"), - /* K2 */ be_nested_str_literal("WS2812"), - /* K3 */ be_const_int(0), - /* K4 */ be_nested_str_literal("valuer_error"), - /* K5 */ be_nested_str_literal("no GPIO specified for neopixelbus"), - /* K6 */ be_nested_str_literal("ctor"), - /* K7 */ be_nested_str_literal("_p"), - /* K8 */ be_nested_str_literal("internal_error"), - /* K9 */ be_nested_str_literal("couldn't not initialize noepixelbus"), - /* K10 */ be_nested_str_literal("begin"), - }), - (be_nested_const_str("init", 380752755, 4)), + 0, /* has constants */ + NULL, /* no const */ + (be_nested_const_str("pixels_buffer", 1229555807, 13)), ((bstring*) &be_const_str_input), - ( &(const binstruction[32]) { /* code */ - 0x50140200, // 0000 LDBOOL R5 1 0 - 0x90020005, // 0001 SETMBR R0 K0 R5 - 0x4C140000, // 0002 LDNIL R5 - 0x1C140405, // 0003 EQ R5 R2 R5 - 0x78160008, // 0004 JMPF R5 #000E - 0x8C140501, // 0005 GETMET R5 R2 K1 - 0x881C0502, // 0006 GETMBR R7 R2 K2 - 0x7C140400, // 0007 CALL R5 2 - 0x28140B03, // 0008 GE R5 R5 K3 - 0x78160003, // 0009 JMPF R5 #000E - 0x8C140501, // 000A GETMET R5 R2 K1 - 0x881C0502, // 000B GETMBR R7 R2 K2 - 0x7C140400, // 000C CALL R5 2 - 0x5C080A00, // 000D MOVE R2 R5 - 0x4C140000, // 000E LDNIL R5 - 0x1C140405, // 000F EQ R5 R2 R5 - 0x78160000, // 0010 JMPF R5 #0012 - 0xB0060905, // 0011 RAISE 1 K4 K5 - 0x8C140106, // 0012 GETMET R5 R0 K6 - 0x5C1C0200, // 0013 MOVE R7 R1 - 0x5C200400, // 0014 MOVE R8 R2 - 0x5C240600, // 0015 MOVE R9 R3 - 0x5C280800, // 0016 MOVE R10 R4 - 0x7C140A00, // 0017 CALL R5 5 - 0x88140107, // 0018 GETMBR R5 R0 K7 - 0x4C180000, // 0019 LDNIL R6 - 0x1C140A06, // 001A EQ R5 R5 R6 - 0x78160000, // 001B JMPF R5 #001D - 0xB0061109, // 001C RAISE 1 K8 K9 - 0x8C14010A, // 001D GETMET R5 R0 K10 - 0x7C140200, // 001E CALL R5 1 - 0x80000000, // 001F RET 0 + ( &(const binstruction[ 2]) { /* code */ + 0x4C040000, // 0000 LDNIL R1 + 0x80040200, // 0001 RET 1 R1 }) ) ); @@ -166,12 +374,48 @@ be_local_closure(Leds_init, /* name */ /******************************************************************** -** Solidified function: set_pixel_color +** Solidified function: init ********************************************************************/ -be_local_closure(Leds_set_pixel_color, /* name */ +be_local_closure(Leds_matrix_init, /* name */ be_nested_proto( - 12, /* nstack */ - 4, /* argc */ + 6, /* nstack */ + 5, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_literal("strip"), + /* K1 */ be_nested_str_literal("offset"), + /* K2 */ be_nested_str_literal("h"), + /* K3 */ be_nested_str_literal("w"), + /* K4 */ be_nested_str_literal("alternate"), + }), + (be_nested_const_str("init", 380752755, 4)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 7]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x90020204, // 0001 SETMBR R0 K1 R4 + 0x90020403, // 0002 SETMBR R0 K2 R3 + 0x90020602, // 0003 SETMBR R0 K3 R2 + 0x50140000, // 0004 LDBOOL R5 0 0 + 0x90020805, // 0005 SETMBR R0 K4 R5 + 0x80000000, // 0006 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: dirty +********************************************************************/ +be_local_closure(Leds_matrix_dirty, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ 0, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ @@ -179,21 +423,229 @@ be_local_closure(Leds_set_pixel_color, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_literal("call_native"), - /* K1 */ be_nested_str_literal("to_gamma"), + /* K0 */ be_nested_str_literal("strip"), + /* K1 */ be_nested_str_literal("dirty"), }), - (be_nested_const_str("set_pixel_color", 1275248356, 15)), + (be_nested_const_str("dirty", -1627386213, 5)), ((bstring*) &be_const_str_input), - ( &(const binstruction[ 9]) { /* code */ - 0x8C100100, // 0000 GETMET R4 R0 K0 - 0x541A0009, // 0001 LDINT R6 10 - 0x5C1C0200, // 0002 MOVE R7 R1 - 0x8C200101, // 0003 GETMET R8 R0 K1 - 0x5C280400, // 0004 MOVE R10 R2 - 0x5C2C0600, // 0005 MOVE R11 R3 - 0x7C200600, // 0006 CALL R8 3 - 0x7C100800, // 0007 CALL R4 4 - 0x80000000, // 0008 RET 0 + ( &(const binstruction[ 4]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x7C040200, // 0002 CALL R1 1 + 0x80000000, // 0003 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_pixel_color +********************************************************************/ +be_local_closure(Leds_matrix_get_pixel_color, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_literal("strip"), + /* K1 */ be_nested_str_literal("get_pixel_color"), + /* K2 */ be_nested_str_literal("offseta"), + }), + (be_nested_const_str("get_pixel_color", 337490048, 15)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 6]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x88100102, // 0002 GETMBR R4 R0 K2 + 0x00100204, // 0003 ADD R4 R1 R4 + 0x7C080400, // 0004 CALL R2 2 + 0x80040400, // 0005 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_alternate +********************************************************************/ +be_local_closure(Leds_matrix_get_alternate, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_literal("alternate"), + }), + (be_nested_const_str("get_alternate", 1450148894, 13)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: begin +********************************************************************/ +be_local_closure(Leds_matrix_begin, /* name */ + be_nested_proto( + 1, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + (be_nested_const_str("begin", 1748273790, 5)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: can_show +********************************************************************/ +be_local_closure(Leds_matrix_can_show, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_literal("strip"), + /* K1 */ be_nested_str_literal("can_show"), + }), + (be_nested_const_str("can_show", 960091187, 8)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 4]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x7C040200, // 0002 CALL R1 1 + 0x80040200, // 0003 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Leds_matrix +********************************************************************/ +be_local_class(Leds_matrix, + 5, + NULL, + be_nested_map(21, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_nested_key("pixel_count", -1855836553, 11, -1), be_const_closure(Leds_matrix_pixel_count_closure) }, + { be_nested_key("h", -317966505, 1, 6), be_const_var(2) }, + { be_nested_key("set_alternate", 1709680562, 13, 7), be_const_closure(Leds_matrix_set_alternate_closure) }, + { be_nested_key("pixel_size", -2085831511, 10, 16), be_const_closure(Leds_matrix_pixel_size_closure) }, + { be_nested_key("set_pixel_color", 1275248356, 15, 19), be_const_closure(Leds_matrix_set_pixel_color_closure) }, + { be_nested_key("set_matrix_pixel_color", 1197149462, 22, 10), be_const_closure(Leds_matrix_set_matrix_pixel_color_closure) }, + { be_nested_key("show", -1454906820, 4, -1), be_const_closure(Leds_matrix_show_closure) }, + { be_nested_key("alternate", 1140253277, 9, -1), be_const_var(4) }, + { be_nested_key("strip", -48555823, 5, -1), be_const_var(0) }, + { be_nested_key("clear_to", -766965166, 8, -1), be_const_closure(Leds_matrix_clear_to_closure) }, + { be_nested_key("w", -234078410, 1, 15), be_const_var(3) }, + { be_nested_key("pixels_buffer", 1229555807, 13, -1), be_const_closure(Leds_matrix_pixels_buffer_closure) }, + { be_nested_key("init", 380752755, 4, -1), be_const_closure(Leds_matrix_init_closure) }, + { be_nested_key("dirty", -1627386213, 5, -1), be_const_closure(Leds_matrix_dirty_closure) }, + { be_nested_key("get_pixel_color", 337490048, 15, -1), be_const_closure(Leds_matrix_get_pixel_color_closure) }, + { be_nested_key("get_alternate", 1450148894, 13, 17), be_const_closure(Leds_matrix_get_alternate_closure) }, + { be_nested_key("offset", 348705738, 6, 8), be_const_var(1) }, + { be_nested_key("clear", 1550717474, 5, -1), be_const_closure(Leds_matrix_clear_closure) }, + { be_nested_key("begin", 1748273790, 5, -1), be_const_closure(Leds_matrix_begin_closure) }, + { be_nested_key("is_dirty", 418034110, 8, -1), be_const_closure(Leds_matrix_is_dirty_closure) }, + { be_nested_key("can_show", 960091187, 8, -1), be_const_closure(Leds_matrix_can_show_closure) }, + })), + be_str_literal("Leds_matrix") +); + +/******************************************************************** +** Solidified function: create_matrix +********************************************************************/ +be_local_closure(Leds_create_matrix, /* name */ + be_nested_proto( + 10, /* nstack */ + 4, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_const_int(0), + /* K1 */ be_nested_str_literal("leds"), + /* K2 */ be_nested_str_literal("value_error"), + /* K3 */ be_nested_str_literal("out of range"), + /* K4 */ be_const_class(be_class_Leds_matrix), + }), + (be_nested_const_str("create_matrix", -766781373, 13)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[37]) { /* code */ + 0x60100009, // 0000 GETGBL R4 G9 + 0x5C140600, // 0001 MOVE R5 R3 + 0x7C100200, // 0002 CALL R4 1 + 0x5C0C0800, // 0003 MOVE R3 R4 + 0x60100009, // 0004 GETGBL R4 G9 + 0x5C140200, // 0005 MOVE R5 R1 + 0x7C100200, // 0006 CALL R4 1 + 0x5C040800, // 0007 MOVE R1 R4 + 0x60100009, // 0008 GETGBL R4 G9 + 0x5C140400, // 0009 MOVE R5 R2 + 0x7C100200, // 000A CALL R4 1 + 0x5C080800, // 000B MOVE R2 R4 + 0x4C100000, // 000C LDNIL R4 + 0x1C100604, // 000D EQ R4 R3 R4 + 0x78120000, // 000E JMPF R4 #0010 + 0x580C0000, // 000F LDCONST R3 K0 + 0x08100202, // 0010 MUL R4 R1 R2 + 0x00100803, // 0011 ADD R4 R4 R3 + 0x88140101, // 0012 GETMBR R5 R0 K1 + 0x24100805, // 0013 GT R4 R4 R5 + 0x74120005, // 0014 JMPT R4 #001B + 0x14100500, // 0015 LT R4 R2 K0 + 0x74120003, // 0016 JMPT R4 #001B + 0x14100300, // 0017 LT R4 R1 K0 + 0x74120001, // 0018 JMPT R4 #001B + 0x14100700, // 0019 LT R4 R3 K0 + 0x78120000, // 001A JMPF R4 #001C + 0xB0060503, // 001B RAISE 1 K2 K3 + 0x58100004, // 001C LDCONST R4 K4 + 0xB4000004, // 001D CLASS K4 + 0x5C140800, // 001E MOVE R5 R4 + 0x5C180000, // 001F MOVE R6 R0 + 0x5C1C0200, // 0020 MOVE R7 R1 + 0x5C200400, // 0021 MOVE R8 R2 + 0x5C240600, // 0022 MOVE R9 R3 + 0x7C140800, // 0023 CALL R5 4 + 0x80040A00, // 0024 RET 1 R5 }) ) ); @@ -358,29 +810,37 @@ be_local_closure(Leds_pixel_count, /* name */ /******************************************************************** -** Solidified function: can_show +** Solidified function: matrix ********************************************************************/ -be_local_closure(Leds_can_show, /* name */ +be_local_closure(Leds_matrix, /* name */ be_nested_proto( - 4, /* nstack */ - 1, /* argc */ + 10, /* nstack */ + 4, /* argc */ 0, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_literal("call_native"), - /* K1 */ be_const_int(3), + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_literal("Leds"), + /* K1 */ be_nested_str_literal("create_matrix"), + /* K2 */ be_const_int(0), }), - (be_nested_const_str("can_show", 960091187, 8)), + (be_nested_const_str("matrix", 365099244, 6)), ((bstring*) &be_const_str_input), - ( &(const binstruction[ 4]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x580C0001, // 0001 LDCONST R3 K1 - 0x7C040400, // 0002 CALL R1 2 - 0x80040200, // 0003 RET 1 R1 + ( &(const binstruction[11]) { /* code */ + 0xB8120000, // 0000 GETNGBL R4 K0 + 0x08140001, // 0001 MUL R5 R0 R1 + 0x5C180400, // 0002 MOVE R6 R2 + 0x5C1C0600, // 0003 MOVE R7 R3 + 0x7C100600, // 0004 CALL R4 3 + 0x8C140901, // 0005 GETMET R5 R4 K1 + 0x5C1C0000, // 0006 MOVE R7 R0 + 0x5C200200, // 0007 MOVE R8 R1 + 0x58240002, // 0008 LDCONST R9 K2 + 0x7C140800, // 0009 CALL R5 4 + 0x80040A00, // 000A RET 1 R5 }) ) ); @@ -417,9 +877,9 @@ be_local_closure(Leds_pixel_size, /* name */ /******************************************************************** -** Solidified function: dirty +** Solidified function: pixels_buffer ********************************************************************/ -be_local_closure(Leds_dirty, /* name */ +be_local_closure(Leds_pixels_buffer, /* name */ be_nested_proto( 4, /* nstack */ 1, /* argc */ @@ -432,13 +892,13 @@ be_local_closure(Leds_dirty, /* name */ ( &(const bvalue[ 1]) { /* constants */ /* K0 */ be_nested_str_literal("call_native"), }), - (be_nested_const_str("dirty", -1627386213, 5)), + (be_nested_const_str("pixels_buffer", 1229555807, 13)), ((bstring*) &be_const_str_input), ( &(const binstruction[ 4]) { /* code */ 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x540E0004, // 0001 LDINT R3 5 + 0x540E0005, // 0001 LDINT R3 6 0x7C040400, // 0002 CALL R1 2 - 0x80000000, // 0003 RET 0 + 0x80040200, // 0003 RET 1 R1 }) ) ); @@ -446,9 +906,74 @@ be_local_closure(Leds_dirty, /* name */ /******************************************************************** -** Solidified function: show +** Solidified function: get_pixel_color ********************************************************************/ -be_local_closure(Leds_show, /* name */ +be_local_closure(Leds_get_pixel_color, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_literal("call_native"), + }), + (be_nested_const_str("get_pixel_color", 337490048, 15)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 5]) { /* code */ + 0x8C080100, // 0000 GETMET R2 R0 K0 + 0x5412000A, // 0001 LDINT R4 11 + 0x5C140200, // 0002 MOVE R5 R1 + 0x7C080600, // 0003 CALL R2 3 + 0x80040400, // 0004 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_pixel_color +********************************************************************/ +be_local_closure(Leds_set_pixel_color, /* name */ + be_nested_proto( + 12, /* nstack */ + 4, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_literal("call_native"), + /* K1 */ be_nested_str_literal("to_gamma"), + }), + (be_nested_const_str("set_pixel_color", 1275248356, 15)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 9]) { /* code */ + 0x8C100100, // 0000 GETMET R4 R0 K0 + 0x541A0009, // 0001 LDINT R6 10 + 0x5C1C0200, // 0002 MOVE R7 R1 + 0x8C200101, // 0003 GETMET R8 R0 K1 + 0x5C280400, // 0004 MOVE R10 R2 + 0x5C2C0600, // 0005 MOVE R11 R3 + 0x7C200600, // 0006 CALL R8 3 + 0x7C100800, // 0007 CALL R4 4 + 0x80000000, // 0008 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: is_dirty +********************************************************************/ +be_local_closure(Leds_is_dirty, /* name */ be_nested_proto( 4, /* nstack */ 1, /* argc */ @@ -458,17 +983,88 @@ be_local_closure(Leds_show, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ + ( &(const bvalue[ 1]) { /* constants */ /* K0 */ be_nested_str_literal("call_native"), - /* K1 */ be_const_int(2), }), - (be_nested_const_str("show", -1454906820, 4)), + (be_nested_const_str("is_dirty", 418034110, 8)), ((bstring*) &be_const_str_input), ( &(const binstruction[ 4]) { /* code */ 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x580C0001, // 0001 LDCONST R3 K1 + 0x540E0003, // 0001 LDINT R3 4 0x7C040400, // 0002 CALL R1 2 - 0x80000000, // 0003 RET 0 + 0x80040200, // 0003 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Leds_init, /* name */ + be_nested_proto( + 11, /* nstack */ + 5, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[12]) { /* constants */ + /* K0 */ be_nested_str_literal("gamma"), + /* K1 */ be_nested_str_literal("leds"), + /* K2 */ be_nested_str_literal("pin"), + /* K3 */ be_nested_str_literal("WS2812"), + /* K4 */ be_const_int(0), + /* K5 */ be_nested_str_literal("valuer_error"), + /* K6 */ be_nested_str_literal("no GPIO specified for neopixelbus"), + /* K7 */ be_nested_str_literal("ctor"), + /* K8 */ be_nested_str_literal("_p"), + /* K9 */ be_nested_str_literal("internal_error"), + /* K10 */ be_nested_str_literal("couldn't not initialize noepixelbus"), + /* K11 */ be_nested_str_literal("begin"), + }), + (be_nested_const_str("init", 380752755, 4)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[36]) { /* code */ + 0x50140200, // 0000 LDBOOL R5 1 0 + 0x90020005, // 0001 SETMBR R0 K0 R5 + 0x60140009, // 0002 GETGBL R5 G9 + 0x5C180200, // 0003 MOVE R6 R1 + 0x7C140200, // 0004 CALL R5 1 + 0x90020205, // 0005 SETMBR R0 K1 R5 + 0x4C140000, // 0006 LDNIL R5 + 0x1C140405, // 0007 EQ R5 R2 R5 + 0x78160008, // 0008 JMPF R5 #0012 + 0x8C140502, // 0009 GETMET R5 R2 K2 + 0x881C0503, // 000A GETMBR R7 R2 K3 + 0x7C140400, // 000B CALL R5 2 + 0x28140B04, // 000C GE R5 R5 K4 + 0x78160003, // 000D JMPF R5 #0012 + 0x8C140502, // 000E GETMET R5 R2 K2 + 0x881C0503, // 000F GETMBR R7 R2 K3 + 0x7C140400, // 0010 CALL R5 2 + 0x5C080A00, // 0011 MOVE R2 R5 + 0x4C140000, // 0012 LDNIL R5 + 0x1C140405, // 0013 EQ R5 R2 R5 + 0x78160000, // 0014 JMPF R5 #0016 + 0xB0060B06, // 0015 RAISE 1 K5 K6 + 0x8C140107, // 0016 GETMET R5 R0 K7 + 0x881C0101, // 0017 GETMBR R7 R0 K1 + 0x5C200400, // 0018 MOVE R8 R2 + 0x5C240600, // 0019 MOVE R9 R3 + 0x5C280800, // 001A MOVE R10 R4 + 0x7C140A00, // 001B CALL R5 5 + 0x88140108, // 001C GETMBR R5 R0 K8 + 0x4C180000, // 001D LDNIL R6 + 0x1C140A06, // 001E EQ R5 R5 R6 + 0x78160000, // 001F JMPF R5 #0021 + 0xB006130A, // 0020 RAISE 1 K9 K10 + 0x8C14010B, // 0021 GETMET R5 R0 K11 + 0x7C140200, // 0022 CALL R5 1 + 0x80000000, // 0023 RET 0 }) ) ); @@ -510,9 +1106,9 @@ be_local_closure(Leds_clear_to, /* name */ /******************************************************************** -** Solidified function: is_dirty +** Solidified function: can_show ********************************************************************/ -be_local_closure(Leds_is_dirty, /* name */ +be_local_closure(Leds_can_show, /* name */ be_nested_proto( 4, /* nstack */ 1, /* argc */ @@ -522,14 +1118,15 @@ be_local_closure(Leds_is_dirty, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ + ( &(const bvalue[ 2]) { /* constants */ /* K0 */ be_nested_str_literal("call_native"), + /* K1 */ be_const_int(3), }), - (be_nested_const_str("is_dirty", 418034110, 8)), + (be_nested_const_str("can_show", 960091187, 8)), ((bstring*) &be_const_str_input), ( &(const binstruction[ 4]) { /* code */ 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x540E0003, // 0001 LDINT R3 4 + 0x580C0001, // 0001 LDCONST R3 K1 0x7C040400, // 0002 CALL R1 2 0x80040200, // 0003 RET 1 R1 }) @@ -538,6 +1135,69 @@ be_local_closure(Leds_is_dirty, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: clear +********************************************************************/ +be_local_closure(Leds_clear, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_literal("clear_to"), + /* K1 */ be_const_int(0), + /* K2 */ be_nested_str_literal("show"), + }), + (be_nested_const_str("clear", 1550717474, 5)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 6]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x580C0001, // 0001 LDCONST R3 K1 + 0x7C040400, // 0002 CALL R1 2 + 0x8C040102, // 0003 GETMET R1 R0 K2 + 0x7C040200, // 0004 CALL R1 1 + 0x80000000, // 0005 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: show +********************************************************************/ +be_local_closure(Leds_show, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_literal("call_native"), + /* K1 */ be_const_int(2), + }), + (be_nested_const_str("show", -1454906820, 4)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 4]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x580C0001, // 0001 LDCONST R3 K1 + 0x7C040400, // 0002 CALL R1 2 + 0x80000000, // 0003 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: ctor ********************************************************************/ @@ -580,31 +1240,567 @@ be_local_closure(Leds_ctor, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: dirty +********************************************************************/ +be_local_closure(Leds_dirty, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_literal("call_native"), + }), + (be_nested_const_str("dirty", -1627386213, 5)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 4]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x540E0004, // 0001 LDINT R3 5 + 0x7C040400, // 0002 CALL R1 2 + 0x80000000, // 0003 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_pixel_color +********************************************************************/ +be_local_closure(Leds_segment_get_pixel_color, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_literal("strip"), + /* K1 */ be_nested_str_literal("get_pixel_color"), + /* K2 */ be_nested_str_literal("offseta"), + }), + (be_nested_const_str("get_pixel_color", 337490048, 15)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 6]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x88100102, // 0002 GETMBR R4 R0 K2 + 0x00100204, // 0003 ADD R4 R1 R4 + 0x7C080400, // 0004 CALL R2 2 + 0x80040400, // 0005 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: clear_to +********************************************************************/ +be_local_closure(Leds_segment_clear_to, /* name */ + be_nested_proto( + 9, /* nstack */ + 3, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_const_int(0), + /* K1 */ be_nested_str_literal("leds"), + /* K2 */ be_nested_str_literal("strip"), + /* K3 */ be_nested_str_literal("set_pixel_color"), + /* K4 */ be_nested_str_literal("offset"), + /* K5 */ be_const_int(1), + }), + (be_nested_const_str("clear_to", -766965166, 8)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[14]) { /* code */ + 0x580C0000, // 0000 LDCONST R3 K0 + 0x88100101, // 0001 GETMBR R4 R0 K1 + 0x14100604, // 0002 LT R4 R3 R4 + 0x78120008, // 0003 JMPF R4 #000D + 0x88100102, // 0004 GETMBR R4 R0 K2 + 0x8C100903, // 0005 GETMET R4 R4 K3 + 0x88180104, // 0006 GETMBR R6 R0 K4 + 0x00180606, // 0007 ADD R6 R3 R6 + 0x5C1C0200, // 0008 MOVE R7 R1 + 0x5C200400, // 0009 MOVE R8 R2 + 0x7C100800, // 000A CALL R4 4 + 0x000C0705, // 000B ADD R3 R3 K5 + 0x7001FFF3, // 000C JMP #0001 + 0x80000000, // 000D RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: can_show +********************************************************************/ +be_local_closure(Leds_segment_can_show, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_literal("strip"), + /* K1 */ be_nested_str_literal("can_show"), + }), + (be_nested_const_str("can_show", 960091187, 8)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 4]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x7C040200, // 0002 CALL R1 1 + 0x80040200, // 0003 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_pixel_color +********************************************************************/ +be_local_closure(Leds_segment_set_pixel_color, /* name */ + be_nested_proto( + 9, /* nstack */ + 4, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_literal("strip"), + /* K1 */ be_nested_str_literal("set_pixel_color"), + /* K2 */ be_nested_str_literal("offset"), + }), + (be_nested_const_str("set_pixel_color", 1275248356, 15)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 8]) { /* code */ + 0x88100100, // 0000 GETMBR R4 R0 K0 + 0x8C100901, // 0001 GETMET R4 R4 K1 + 0x88180102, // 0002 GETMBR R6 R0 K2 + 0x00180206, // 0003 ADD R6 R1 R6 + 0x5C1C0400, // 0004 MOVE R7 R2 + 0x5C200600, // 0005 MOVE R8 R3 + 0x7C100800, // 0006 CALL R4 4 + 0x80000000, // 0007 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: clear +********************************************************************/ +be_local_closure(Leds_segment_clear, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_literal("clear_to"), + /* K1 */ be_const_int(0), + /* K2 */ be_nested_str_literal("show"), + }), + (be_nested_const_str("clear", 1550717474, 5)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 6]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x580C0001, // 0001 LDCONST R3 K1 + 0x7C040400, // 0002 CALL R1 2 + 0x8C040102, // 0003 GETMET R1 R0 K2 + 0x7C040200, // 0004 CALL R1 1 + 0x80000000, // 0005 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: begin +********************************************************************/ +be_local_closure(Leds_segment_begin, /* name */ + be_nested_proto( + 1, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + (be_nested_const_str("begin", 1748273790, 5)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: pixel_count +********************************************************************/ +be_local_closure(Leds_segment_pixel_count, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_literal("leds"), + }), + (be_nested_const_str("pixel_count", -1855836553, 11)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Leds_segment_init, /* name */ + be_nested_proto( + 6, /* nstack */ + 4, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_literal("strip"), + /* K1 */ be_nested_str_literal("offset"), + /* K2 */ be_nested_str_literal("leds"), + }), + (be_nested_const_str("init", 380752755, 4)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[10]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x60100009, // 0001 GETGBL R4 G9 + 0x5C140400, // 0002 MOVE R5 R2 + 0x7C100200, // 0003 CALL R4 1 + 0x90020204, // 0004 SETMBR R0 K1 R4 + 0x60100009, // 0005 GETGBL R4 G9 + 0x5C140600, // 0006 MOVE R5 R3 + 0x7C100200, // 0007 CALL R4 1 + 0x90020404, // 0008 SETMBR R0 K2 R4 + 0x80000000, // 0009 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: pixel_size +********************************************************************/ +be_local_closure(Leds_segment_pixel_size, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_literal("strip"), + /* K1 */ be_nested_str_literal("pixel_size"), + }), + (be_nested_const_str("pixel_size", -2085831511, 10)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 4]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x7C040200, // 0002 CALL R1 1 + 0x80040200, // 0003 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: dirty +********************************************************************/ +be_local_closure(Leds_segment_dirty, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_literal("strip"), + /* K1 */ be_nested_str_literal("dirty"), + }), + (be_nested_const_str("dirty", -1627386213, 5)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 4]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x7C040200, // 0002 CALL R1 1 + 0x80000000, // 0003 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: show +********************************************************************/ +be_local_closure(Leds_segment_show, /* name */ + be_nested_proto( + 4, /* nstack */ + 2, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_literal("offset"), + /* K1 */ be_const_int(0), + /* K2 */ be_nested_str_literal("leds"), + /* K3 */ be_nested_str_literal("strip"), + /* K4 */ be_nested_str_literal("show"), + }), + (be_nested_const_str("show", -1454906820, 4)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[16]) { /* code */ + 0x60080017, // 0000 GETGBL R2 G23 + 0x5C0C0200, // 0001 MOVE R3 R1 + 0x7C080200, // 0002 CALL R2 1 + 0x740A0007, // 0003 JMPT R2 #000C + 0x88080100, // 0004 GETMBR R2 R0 K0 + 0x1C080501, // 0005 EQ R2 R2 K1 + 0x780A0007, // 0006 JMPF R2 #000F + 0x88080102, // 0007 GETMBR R2 R0 K2 + 0x880C0103, // 0008 GETMBR R3 R0 K3 + 0x880C0702, // 0009 GETMBR R3 R3 K2 + 0x1C080403, // 000A EQ R2 R2 R3 + 0x780A0002, // 000B JMPF R2 #000F + 0x88080103, // 000C GETMBR R2 R0 K3 + 0x8C080504, // 000D GETMET R2 R2 K4 + 0x7C080200, // 000E CALL R2 1 + 0x80000000, // 000F RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: is_dirty +********************************************************************/ +be_local_closure(Leds_segment_is_dirty, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_literal("strip"), + /* K1 */ be_nested_str_literal("is_dirty"), + }), + (be_nested_const_str("is_dirty", 418034110, 8)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 4]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x7C040200, // 0002 CALL R1 1 + 0x80040200, // 0003 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: pixels_buffer +********************************************************************/ +be_local_closure(Leds_segment_pixels_buffer, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + (be_nested_const_str("pixels_buffer", 1229555807, 13)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[ 2]) { /* code */ + 0x4C040000, // 0000 LDNIL R1 + 0x80040200, // 0001 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Leds_segment +********************************************************************/ +be_local_class(Leds_segment, + 3, + NULL, + be_nested_map(16, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_nested_key("get_pixel_color", 337490048, 15, -1), be_const_closure(Leds_segment_get_pixel_color_closure) }, + { be_nested_key("strip", -48555823, 5, -1), be_const_var(0) }, + { be_nested_key("clear_to", -766965166, 8, 5), be_const_closure(Leds_segment_clear_to_closure) }, + { be_nested_key("can_show", 960091187, 8, 13), be_const_closure(Leds_segment_can_show_closure) }, + { be_nested_key("set_pixel_color", 1275248356, 15, -1), be_const_closure(Leds_segment_set_pixel_color_closure) }, + { be_nested_key("clear", 1550717474, 5, -1), be_const_closure(Leds_segment_clear_closure) }, + { be_nested_key("is_dirty", 418034110, 8, -1), be_const_closure(Leds_segment_is_dirty_closure) }, + { be_nested_key("pixel_count", -1855836553, 11, -1), be_const_closure(Leds_segment_pixel_count_closure) }, + { be_nested_key("leds", 558858555, 4, -1), be_const_var(2) }, + { be_nested_key("pixel_size", -2085831511, 10, -1), be_const_closure(Leds_segment_pixel_size_closure) }, + { be_nested_key("offset", 348705738, 6, -1), be_const_var(1) }, + { be_nested_key("dirty", -1627386213, 5, 8), be_const_closure(Leds_segment_dirty_closure) }, + { be_nested_key("show", -1454906820, 4, -1), be_const_closure(Leds_segment_show_closure) }, + { be_nested_key("init", 380752755, 4, -1), be_const_closure(Leds_segment_init_closure) }, + { be_nested_key("begin", 1748273790, 5, 6), be_const_closure(Leds_segment_begin_closure) }, + { be_nested_key("pixels_buffer", 1229555807, 13, -1), be_const_closure(Leds_segment_pixels_buffer_closure) }, + })), + be_str_literal("Leds_segment") +); + +/******************************************************************** +** Solidified function: create_segment +********************************************************************/ +be_local_closure(Leds_create_segment, /* name */ + be_nested_proto( + 8, /* nstack */ + 3, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_literal("leds"), + /* K1 */ be_const_int(0), + /* K2 */ be_nested_str_literal("value_error"), + /* K3 */ be_nested_str_literal("out of range"), + /* K4 */ be_const_class(be_class_Leds_segment), + }), + (be_nested_const_str("create_segment", -431444577, 14)), + ((bstring*) &be_const_str_input), + ( &(const binstruction[23]) { /* code */ + 0x600C0009, // 0000 GETGBL R3 G9 + 0x5C100200, // 0001 MOVE R4 R1 + 0x7C0C0200, // 0002 CALL R3 1 + 0x60100009, // 0003 GETGBL R4 G9 + 0x5C140400, // 0004 MOVE R5 R2 + 0x7C100200, // 0005 CALL R4 1 + 0x000C0604, // 0006 ADD R3 R3 R4 + 0x88100100, // 0007 GETMBR R4 R0 K0 + 0x240C0604, // 0008 GT R3 R3 R4 + 0x740E0003, // 0009 JMPT R3 #000E + 0x140C0301, // 000A LT R3 R1 K1 + 0x740E0001, // 000B JMPT R3 #000E + 0x140C0501, // 000C LT R3 R2 K1 + 0x780E0000, // 000D JMPF R3 #000F + 0xB0060503, // 000E RAISE 1 K2 K3 + 0x580C0004, // 000F LDCONST R3 K4 + 0xB4000004, // 0010 CLASS K4 + 0x5C100600, // 0011 MOVE R4 R3 + 0x5C140000, // 0012 MOVE R5 R0 + 0x5C180200, // 0013 MOVE R6 R1 + 0x5C1C0400, // 0014 MOVE R7 R2 + 0x7C100600, // 0015 CALL R4 3 + 0x80040800, // 0016 RET 1 R4 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified class: Leds ********************************************************************/ extern const bclass be_class_Leds_ntv; be_local_class(Leds, - 1, + 2, &be_class_Leds_ntv, - be_nested_map(16, + be_nested_map(20, ( (struct bmapnode*) &(const bmapnode[]) { - { be_nested_key("get_pixel_color", 337490048, 15, -1), be_const_closure(Leds_get_pixel_color_closure) }, - { be_nested_key("ctor", 375399343, 4, -1), be_const_closure(Leds_ctor_closure) }, - { be_nested_key("clear", 1550717474, 5, 8), be_const_closure(Leds_clear_closure) }, - { be_nested_key("init", 380752755, 4, 13), be_const_closure(Leds_init_closure) }, - { be_nested_key("set_pixel_color", 1275248356, 15, -1), be_const_closure(Leds_set_pixel_color_closure) }, - { be_nested_key("is_dirty", 418034110, 8, -1), be_const_closure(Leds_is_dirty_closure) }, - { be_nested_key("to_gamma", 1597139862, 8, -1), be_const_closure(Leds_to_gamma_closure) }, { be_nested_key("pixel_count", -1855836553, 11, -1), be_const_closure(Leds_pixel_count_closure) }, - { be_nested_key("clear_to", -766965166, 8, -1), be_const_closure(Leds_clear_to_closure) }, + { be_nested_key("dirty", -1627386213, 5, 6), be_const_closure(Leds_dirty_closure) }, + { be_nested_key("to_gamma", 1597139862, 8, -1), be_const_closure(Leds_to_gamma_closure) }, + { be_nested_key("create_matrix", -766781373, 13, 1), be_const_closure(Leds_create_matrix_closure) }, + { be_nested_key("matrix", 365099244, 6, -1), be_const_static_closure(Leds_matrix_closure) }, { be_nested_key("pixel_size", -2085831511, 10, -1), be_const_closure(Leds_pixel_size_closure) }, - { be_nested_key("gamma", -802614262, 5, -1), be_const_var(0) }, - { be_nested_key("dirty", -1627386213, 5, -1), be_const_closure(Leds_dirty_closure) }, + { be_nested_key("ctor", 375399343, 4, 0), be_const_closure(Leds_ctor_closure) }, + { be_nested_key("pixels_buffer", 1229555807, 13, 13), be_const_closure(Leds_pixels_buffer_closure) }, + { be_nested_key("get_pixel_color", 337490048, 15, -1), be_const_closure(Leds_get_pixel_color_closure) }, { be_nested_key("show", -1454906820, 4, -1), be_const_closure(Leds_show_closure) }, + { be_nested_key("begin", 1748273790, 5, 17), be_const_closure(Leds_begin_closure) }, + { be_nested_key("leds", 558858555, 4, -1), be_const_var(1) }, + { be_nested_key("clear", 1550717474, 5, -1), be_const_closure(Leds_clear_closure) }, { be_nested_key("can_show", 960091187, 8, -1), be_const_closure(Leds_can_show_closure) }, - { be_nested_key("begin", 1748273790, 5, 5), be_const_closure(Leds_begin_closure) }, - { be_nested_key("pixels_buffer", 1229555807, 13, 1), be_const_closure(Leds_pixels_buffer_closure) }, + { be_nested_key("gamma", -802614262, 5, 12), be_const_var(0) }, + { be_nested_key("init", 380752755, 4, 11), be_const_closure(Leds_init_closure) }, + { be_nested_key("set_pixel_color", 1275248356, 15, 9), be_const_closure(Leds_set_pixel_color_closure) }, + { be_nested_key("clear_to", -766965166, 8, 18), be_const_closure(Leds_clear_to_closure) }, + { be_nested_key("is_dirty", 418034110, 8, -1), be_const_closure(Leds_is_dirty_closure) }, + { be_nested_key("create_segment", -431444577, 14, -1), be_const_closure(Leds_create_segment_closure) }, })), be_str_literal("Leds") ); diff --git a/lib/libesp32/Berry/default/be_leds_matrix_lib.c b/lib/libesp32/Berry/default/be_leds_matrix_lib.c deleted file mode 100644 index 1aafb3db4..000000000 --- a/lib/libesp32/Berry/default/be_leds_matrix_lib.c +++ /dev/null @@ -1,185 +0,0 @@ -/******************************************************************** - * Berry class `Leds_matrix` - * - *******************************************************************/ -#include "be_constobj.h" - -#ifdef USE_WS2812 - -/******************************************************************** -** Solidified function: get_alternate -********************************************************************/ -be_local_closure(Leds_matrix_get_alternate, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_literal("alternate"), - }), - (be_nested_const_str("get_alternate", 1450148894, 13)), - ((bstring*) &be_const_str_input), - ( &(const binstruction[ 2]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x80040200, // 0001 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_alternate -********************************************************************/ -be_local_closure(Leds_matrix_set_alternate, /* name */ - be_nested_proto( - 2, /* nstack */ - 2, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_literal("alternate"), - }), - (be_nested_const_str("set_alternate", 1709680562, 13)), - ((bstring*) &be_const_str_input), - ( &(const binstruction[ 2]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x80000000, // 0001 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_matrix_pixel_color -********************************************************************/ -be_local_closure(Leds_matrix_set_matrix_pixel_color, /* name */ - be_nested_proto( - 10, /* nstack */ - 5, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_literal("alternate"), - /* K1 */ be_const_int(2), - /* K2 */ be_nested_str_literal("set_pixel_color"), - /* K3 */ be_nested_str_literal("w"), - /* K4 */ be_nested_str_literal("h"), - /* K5 */ be_const_int(1), - }), - (be_nested_const_str("set_matrix_pixel_color", 1197149462, 22)), - ((bstring*) &be_const_str_input), - ( &(const binstruction[23]) { /* code */ - 0x88140100, // 0000 GETMBR R5 R0 K0 - 0x7816000C, // 0001 JMPF R5 #000F - 0x10140301, // 0002 MOD R5 R1 K1 - 0x7816000A, // 0003 JMPF R5 #000F - 0x8C140102, // 0004 GETMET R5 R0 K2 - 0x881C0103, // 0005 GETMBR R7 R0 K3 - 0x081C0207, // 0006 MUL R7 R1 R7 - 0x88200104, // 0007 GETMBR R8 R0 K4 - 0x001C0E08, // 0008 ADD R7 R7 R8 - 0x041C0E02, // 0009 SUB R7 R7 R2 - 0x041C0F05, // 000A SUB R7 R7 K5 - 0x5C200600, // 000B MOVE R8 R3 - 0x5C240800, // 000C MOVE R9 R4 - 0x7C140800, // 000D CALL R5 4 - 0x70020006, // 000E JMP #0016 - 0x8C140102, // 000F GETMET R5 R0 K2 - 0x881C0103, // 0010 GETMBR R7 R0 K3 - 0x081C0207, // 0011 MUL R7 R1 R7 - 0x001C0E02, // 0012 ADD R7 R7 R2 - 0x5C200600, // 0013 MOVE R8 R3 - 0x5C240800, // 0014 MOVE R9 R4 - 0x7C140800, // 0015 CALL R5 4 - 0x80000000, // 0016 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(Leds_matrix_init, /* name */ - be_nested_proto( - 10, /* nstack */ - 5, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_literal("w"), - /* K1 */ be_nested_str_literal("h"), - /* K2 */ be_nested_str_literal("alternate"), - /* K3 */ be_nested_str_literal("init"), - }), - (be_nested_const_str("init", 380752755, 4)), - ((bstring*) &be_const_str_input), - ( &(const binstruction[13]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x90020202, // 0001 SETMBR R0 K1 R2 - 0x50140000, // 0002 LDBOOL R5 0 0 - 0x90020405, // 0003 SETMBR R0 K2 R5 - 0x60140003, // 0004 GETGBL R5 G3 - 0x5C180000, // 0005 MOVE R6 R0 - 0x7C140200, // 0006 CALL R5 1 - 0x8C140B03, // 0007 GETMET R5 R5 K3 - 0x081C0202, // 0008 MUL R7 R1 R2 - 0x5C200600, // 0009 MOVE R8 R3 - 0x5C240800, // 000A MOVE R9 R4 - 0x7C140800, // 000B CALL R5 4 - 0x80000000, // 000C RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified class: Leds_matrix -********************************************************************/ -extern const bclass be_class_Leds; -be_local_class(Leds_matrix, - 3, - &be_class_Leds, - be_nested_map(7, - ( (struct bmapnode*) &(const bmapnode[]) { - { be_nested_key("init", 380752755, 4, 3), be_const_closure(Leds_matrix_init_closure) }, - { be_nested_key("h", -317966505, 1, -1), be_const_var(0) }, - { be_nested_key("set_alternate", 1709680562, 13, 6), be_const_closure(Leds_matrix_set_alternate_closure) }, - { be_nested_key("set_matrix_pixel_color", 1197149462, 22, 4), be_const_closure(Leds_matrix_set_matrix_pixel_color_closure) }, - { be_nested_key("w", -234078410, 1, -1), be_const_var(1) }, - { be_nested_key("get_alternate", 1450148894, 13, 0), be_const_closure(Leds_matrix_get_alternate_closure) }, - { be_nested_key("alternate", 1140253277, 9, -1), be_const_var(2) }, - })), - be_str_literal("Leds_matrix") -); -/*******************************************************************/ - -void be_load_Leds_matrix_class(bvm *vm) { - be_pushntvclass(vm, &be_class_Leds_matrix); - be_setglobal(vm, "Leds_matrix"); - be_pop(vm, 1); -} - - -#endif // USE_WS2812 diff --git a/lib/libesp32/Berry/default/be_leds_ntv_lib.c b/lib/libesp32/Berry/default/be_leds_ntv_lib.c index 5affc1c71..357786978 100644 --- a/lib/libesp32/Berry/default/be_leds_ntv_lib.c +++ b/lib/libesp32/Berry/default/be_leds_ntv_lib.c @@ -8,9 +8,7 @@ class Leds_ntv var _p # pointer to internal object of type `NeoPixelBus(uint16_t countPixels, uint8_t pin)` var _t # type of led strip static WS2812_GRB = 1 - static WS2812_GRBW = 2 - static SK6812_GRB = 3 - static SK6812_GRBW = 4 + static SK6812_GRBW = 2 # skeleton for native call def call_native() end @@ -30,15 +28,13 @@ extern int be_neopixelbus_call_native(bvm *vm); be_local_class(Leds_ntv, 2, NULL, - be_nested_map(7, + be_nested_map(5, ( (struct bmapnode*) &(const bmapnode[]) { - { be_nested_key("WS2812_GRB", 1736405692, 10, 5), be_const_int(1) }, - { be_nested_key("_p", 1594591802, 2, -1), be_const_var(0) }, - { be_nested_key("WS2812_GRBW", -660477967, 11, 3), be_const_int(2) }, { be_nested_key("call_native", 1389147405, 11, -1), be_const_func(be_neopixelbus_call_native) }, - { be_nested_key("SK6812_GRBW", 81157857, 11, -1), be_const_int(4) }, { be_nested_key("_t", 1527481326, 2, -1), be_const_var(1) }, - { be_nested_key("SK6812_GRB", 1159411308, 10, 1), be_const_int(3) }, + { be_nested_key("_p", 1594591802, 2, 3), be_const_var(0) }, + { be_nested_key("SK6812_GRBW", 81157857, 11, 4), be_const_int(2) }, + { be_nested_key("WS2812_GRB", 1736405692, 10, -1), be_const_int(1) }, })), be_str_literal("Leds_ntv") ); diff --git a/lib/libesp32/Berry/default/be_modtab.c b/lib/libesp32/Berry/default/be_modtab.c index 5f04457ac..0c54ce990 100644 --- a/lib/libesp32/Berry/default/be_modtab.c +++ b/lib/libesp32/Berry/default/be_modtab.c @@ -138,7 +138,6 @@ extern void be_load_webclient_lib(bvm *vm); extern void be_load_crypto_lib(bvm *vm); extern void be_load_Leds_ntv_class(bvm *vm); extern void be_load_Leds_class(bvm *vm); -extern void be_load_Leds_matrix_class(bvm *vm); extern void be_load_Leds_animator_class(bvm *vm); extern void be_load_ctypes_lib(bvm *vm); @@ -197,7 +196,6 @@ BERRY_API void be_load_custom_libs(bvm *vm) #ifdef USE_WS2812 be_load_Leds_ntv_class(vm); be_load_Leds_class(vm); - be_load_Leds_matrix_class(vm); be_load_Leds_animator_class(vm); #endif // USE_WS2812 #ifdef USE_I2S_AUDIO_BERRY diff --git a/lib/libesp32/Berry/default/embedded/leds.be b/lib/libesp32/Berry/default/embedded/leds.be index 289ad1118..11a0489af 100644 --- a/lib/libesp32/Berry/default/embedded/leds.be +++ b/lib/libesp32/Berry/default/embedded/leds.be @@ -24,12 +24,14 @@ class Leds : Leds_ntv var gamma # if true, apply gamma (true is default) + var leds # number of leds # leds:int = number of leds of the strip # gpio:int (optional) = GPIO for NeoPixel. If not specified, takes the WS2812 gpio # type:int (optional) = Type of LED, defaults to WS2812 RGB # rmt:int (optional) = RMT hardware channel to use, leave default unless you have a good reason def init(leds, gpio, type, rmt) # rmt is optional self.gamma = true # gamma is enabled by default, it should be disabled explicitly if needed + self.leds = int(leds) if gpio == nil && gpio.pin(gpio.WS2812) >= 0 gpio = gpio.pin(gpio.WS2812) @@ -41,7 +43,7 @@ class Leds : Leds_ntv end # initialize the structure - self.ctor(leds, gpio, type, rmt) + self.ctor(self.leds, gpio, type, rmt) if self._p == nil raise "internal_error", "couldn't not initialize noepixelbus" end @@ -124,8 +126,176 @@ class Leds : Leds_ntv b end end + + # `segment` + # create a new `strip` object that maps a part of the current strip + def create_segment(offset, leds) + if int(offset) + int(leds) > self.leds || offset < 0 || leds < 0 + raise "value_error", "out of range" + end + + # inner class + class Leds_segment + var strip + var offset, leds + + def init(strip, offset, leds) + self.strip = strip + self.offset = int(offset) + self.leds = int(leds) + end + + def clear() + self.clear_to(0x000000) + self.show() + end + + def begin() + # do nothing, already being handled by physical strip + end + def show(force) + # don't trigger on segment, you will need to trigger on full strip instead + if bool(force) || (self.offset == 0 && self.leds == self.strip.leds) + self.strip.show() + end + end + def can_show() + return self.strip.can_show() + end + def is_dirty() + return self.strip.is_dirty() + end + def dirty() + self.strip.dirty() + end + def pixels_buffer() + return nil + end + def pixel_size() + return self.strip.pixel_size() + end + def pixel_count() + return self.leds + end + def clear_to(col, bri) + var i = 0 + while i < self.leds + self.strip.set_pixel_color(i + self.offset, col, bri) + i += 1 + end + end + def set_pixel_color(idx, col, bri) + self.strip.set_pixel_color(idx + self.offset, col, bri) + end + def get_pixel_color(idx) + return self.strip.get_pixel_color(idx + self.offseta) + end + end + + return Leds_segment(self, offset, leds) + + end + + def create_matrix(w, h, offset) + offset = int(offset) + w = int(w) + h = int(h) + if offset == nil offset = 0 end + if w * h + offset > self.leds || h < 0 || w < 0 || offset < 0 + raise "value_error", "out of range" + end + + # inner class + class Leds_matrix + var strip + var offset + var h, w + var alternate # are rows in alternate mode (even/odd are reversed) + + def init(strip, w, h, offset) + self.strip = strip + self.offset = offset + self.h = h + self.w = w + self.alternate = false + end + + def clear() + self.clear_to(0x000000) + self.show() + end + + def begin() + # do nothing, already being handled by physical strip + end + def show(force) + # don't trigger on segment, you will need to trigger on full strip instead + if bool(force) || (self.offset == 0 && self.w * self.h == self.strip.leds) + self.strip.show() + end + end + def can_show() + return self.strip.can_show() + end + def is_dirty() + return self.strip.is_dirty() + end + def dirty() + self.strip.dirty() + end + def pixels_buffer() + return nil + end + def pixel_size() + return self.strip.pixel_size() + end + def pixel_count() + return self.w * self.h + end + def clear_to(col, bri) + var i = 0 + while i < self.w * self.h + self.strip.set_pixel_color(i + self.offset, col, bri) + i += 1 + end + end + def set_pixel_color(idx, col, bri) + self.strip.set_pixel_color(idx + self.offset, col, bri) + end + def get_pixel_color(idx) + return self.strip.get_pixel_color(idx + self.offseta) + end + + # Leds_matrix specific + def set_alternate(alt) + self.alternate = alt + end + def get_alternate() + return self.alternate + end + + def set_matrix_pixel_color(x, y, col, bri) + if self.alternate && x % 2 + # reversed line + self.strip.set_pixel_color(x * self.w + self.h - y - 1 + self.offset, col, bri) + else + self.strip.set_pixel_color(x * self.w + y + self.offset, col, bri) + end + end + end + + return Leds_matrix(self, w, h, offset) + + end + + static def matrix(w, h, gpio, rmt) + var strip = Leds(w * h, gpio, rmt) + var matrix = strip.create_matrix(w, h, 0) + return matrix + end end + #- var s = Leds(25, gpio.pin(gpio.WS2812, 1)) @@ -144,34 +314,6 @@ anim() -# -class Leds_matrix : Leds - var h, w - var alternate # are rows in alternate mode (even/odd are reversed) - - def init(w, h, gpio, rmt) - self.w = w - self.h = h - self.alternate = false - super(self).init(w * h, gpio, rmt) - end - - def set_alternate(alt) - self.alternate = alt - end - def get_alternate() - return self.alternate - end - - def set_matrix_pixel_color(x, y, col, bri) - if self.alternate && x % 2 - # reversed line - self.set_pixel_color(x * self.w + self.h - y - 1, col, bri) - else - self.set_pixel_color(x * self.w + y, col, bri) - end - end -end - #- var s = Leds_matrix(5, 5, gpio.pin(gpio.WS2812, 1)) diff --git a/tasmota/berry/leds/rainbow.be b/tasmota/berry/leds/rainbow.be index bb7a4f105..bf3801556 100644 --- a/tasmota/berry/leds/rainbow.be +++ b/tasmota/berry/leds/rainbow.be @@ -11,28 +11,6 @@ rainbow.start() import animate -# https://stackoverflow.com/questions/34187171/fast-integer-square-root-approximation -def fast_sqrt_int(val) - var a, b - - if val < 2 return val end - - a = 1255 # starting point is relatively unimportant - - b = val / a; a = (a+b) /2; - b = val / a; a = (a+b) /2; - b = val / a; a = (a+b) /2; - b = val / a; a = (a+b) /2; - b = val / a; a = (a+b) /2; - b = val / a; a = (a+b) /2; - if (val < 20000) - b = val / a; a = (a+b) /2; - b = val / a; a = (a+b) /2; - end - - return a -end - class Rainbow : Leds_animator var cur_offset # current offset in the palette static palette = [ 0xFF0000, #- red -# @@ -45,6 +23,7 @@ class Rainbow : Leds_animator ] def init(strip, duration) + import animate super(self).init(strip) self.cur_offset = 0 # add an animator to change `self.cur_offset` to each value of the palette @@ -73,7 +52,7 @@ end #- -var strip = Leds_matrix(5,5, gpio.pin(gpio.WS2812, 1)) +var strip = Leds.matrix(5,5, gpio.pin(gpio.WS2812, 1)) var r = Rainbow(strip, 1.0) r.start() @@ -91,6 +70,7 @@ class Rainbow_stripes : Leds_animator ] def init(strip, duration) + import animate super(self).init(strip) self.cur_offset = 0 # add an animator to change `self.cur_offset` to each value of the palette @@ -125,7 +105,7 @@ end #- -var strip = Leds_matrix(5,5, gpio.pin(gpio.WS2812, 1)) +var strip = Leds.matrix(5,5, gpio.pin(gpio.WS2812, 1)) var r = Rainbow_Matrix(strip, 0.5) r.start() @@ -138,6 +118,7 @@ class Round : Leds_animator var h def init(strip, glow_duration, color_duration) + import animate super(self).init(strip) self.cur_val = 5 << 8 self.h = 0 # start with hue = 0 (red) @@ -162,7 +143,7 @@ class Round : Leds_animator var x = 0 while x < w var col = col_ref - var dist = fast_sqrt_int( ((y - ch)*(y - ch) + (x - cw)*(x - cw)) << 16) + var dist = self.fast_sqrt_int( ((y - ch)*(y - ch) + (x - cw)*(x - cw)) << 16) var rel_bri = tasmota.scale_uint(dist, 0, self.cur_val, bri, 0) set_matrix_pixel_color(strip, x, y, col, rel_bri) # simulate the method call without GETMET x += 1 @@ -172,11 +153,32 @@ class Round : Leds_animator strip.show() end + # https://stackoverflow.com/questions/34187171/fast-integer-square-root-approximation + static def fast_sqrt_int(val) + var a, b + + if val < 2 return val end + + a = 1255 # starting point is relatively unimportant + + b = val / a; a = (a+b) /2; + b = val / a; a = (a+b) /2; + b = val / a; a = (a+b) /2; + b = val / a; a = (a+b) /2; + b = val / a; a = (a+b) /2; + b = val / a; a = (a+b) /2; + if (val < 20000) + b = val / a; a = (a+b) /2; + b = val / a; a = (a+b) /2; + end + + return a + end end #- -var strip = Leds_matrix(5,5, gpio.pin(gpio.WS2812, 1)) +var strip = Leds.matrix(5,5, gpio.pin(gpio.WS2812, 1)) var r = Round(strip, 2, 30) r.start() diff --git a/tasmota/xdrv_52_3_berry_leds.ino b/tasmota/xdrv_52_3_berry_leds.ino index 5e7d95b77..1801f1260 100644 --- a/tasmota/xdrv_52_3_berry_leds.ino +++ b/tasmota/xdrv_52_3_berry_leds.ino @@ -28,16 +28,12 @@ enum { ws2812_grb = 1, - ws2812_grbw = 2, - sk6812_grb = 3, - sk6812_grbw = 4, + sk6812_grbw = 2, neopixel_type_end }; typedef NeoPixelBus neopixel_ws2812_grb_t; -typedef NeoPixelBus neopixel_ws2812_grbw_t; -typedef NeoPixelBus neopixel_sk6812_grb_t; typedef NeoPixelBus neopixel_sk6812_grbw_t; @@ -124,10 +120,6 @@ extern "C" { switch (neopixel_type) { case ws2812_grb: strip = new neopixel_ws2812_grb_t(leds, gpio, (NeoBusChannel) rmt); break; - case ws2812_grbw: strip = new neopixel_ws2812_grbw_t(leds, gpio, (NeoBusChannel) rmt); - break; - case sk6812_grb: strip = new neopixel_sk6812_grb_t(leds, gpio, (NeoBusChannel) rmt); - break; case sk6812_grbw: strip = new neopixel_sk6812_grbw_t(leds, gpio, (NeoBusChannel) rmt); break; } @@ -141,8 +133,6 @@ extern "C" { const void * s = be_get_neopixelbus(vm); // raises an exception if pointer is invalid // initialize all possible variants neopixel_ws2812_grb_t * s_ws2812_grb = (leds_type == ws2812_grb) ? (neopixel_ws2812_grb_t*) s : nullptr; - neopixel_ws2812_grbw_t * s_ws2812_grbw = (leds_type == ws2812_grbw) ? (neopixel_ws2812_grbw_t*) s : nullptr; - neopixel_sk6812_grb_t * s_sk6812_grb = (leds_type == sk6812_grb) ? (neopixel_sk6812_grb_t*) s : nullptr; neopixel_sk6812_grbw_t * s_sk6812_grbw = (leds_type == sk6812_grbw) ? (neopixel_sk6812_grbw_t*) s : nullptr; be_pushnil(vm); // push a default `nil` return value @@ -150,46 +140,32 @@ extern "C" { switch (cmd) { case 1: // # 01 : begin void -> void if (s_ws2812_grb) s_ws2812_grb->Begin(); - if (s_ws2812_grbw) s_ws2812_grbw->Begin(); - if (s_sk6812_grb) s_sk6812_grb->Begin(); if (s_sk6812_grbw) s_sk6812_grbw->Begin(); break; case 2: // # 02 : show void -> void if (s_ws2812_grb) s_ws2812_grb->Show(); - if (s_ws2812_grbw) s_ws2812_grbw->Show(); - if (s_sk6812_grb) s_sk6812_grb->Show(); if (s_sk6812_grbw) s_sk6812_grbw->Show(); break; case 3: // # 03 : CanShow void -> bool if (s_ws2812_grb) be_pushbool(vm, s_ws2812_grb->CanShow()); - if (s_ws2812_grbw) be_pushbool(vm, s_ws2812_grbw->CanShow()); - if (s_sk6812_grb) be_pushbool(vm, s_sk6812_grb->CanShow()); if (s_sk6812_grbw) be_pushbool(vm, s_sk6812_grbw->CanShow()); break; case 4: // # 04 : IsDirty void -> bool if (s_ws2812_grb) be_pushbool(vm, s_ws2812_grb->IsDirty()); - if (s_ws2812_grbw) be_pushbool(vm, s_ws2812_grbw->IsDirty()); - if (s_sk6812_grb) be_pushbool(vm, s_sk6812_grb->IsDirty()); if (s_sk6812_grbw) be_pushbool(vm, s_sk6812_grbw->IsDirty()); break; case 5: // # 05 : Dirty void -> void if (s_ws2812_grb) s_ws2812_grb->Dirty(); - if (s_ws2812_grbw) s_ws2812_grbw->Dirty(); - if (s_sk6812_grb) s_sk6812_grb->Dirty(); if (s_sk6812_grbw) s_sk6812_grbw->Dirty(); break; case 6: // # 06 : Pixels void -> bytes() (mapped to the buffer) { size_t pixels_bytes; if (s_ws2812_grb) pixels_bytes = s_ws2812_grb->PixelsSize(); - if (s_ws2812_grbw) pixels_bytes = s_ws2812_grbw->PixelsSize(); - if (s_sk6812_grb) pixels_bytes = s_sk6812_grb->PixelsSize(); if (s_sk6812_grbw) pixels_bytes = s_sk6812_grbw->PixelsSize(); uint8_t * pixels; if (s_ws2812_grb) pixels = s_ws2812_grb->Pixels(); - if (s_ws2812_grbw) pixels = s_ws2812_grbw->Pixels(); - if (s_sk6812_grb) pixels = s_sk6812_grb->Pixels(); if (s_sk6812_grbw) pixels = s_sk6812_grbw->Pixels(); be_getbuiltin(vm, "bytes"); @@ -201,14 +177,10 @@ extern "C" { break; case 7: // # 07 : PixelSize void -> int if (s_ws2812_grb) be_pushint(vm, s_ws2812_grb->PixelSize()); - if (s_ws2812_grbw) be_pushint(vm, s_ws2812_grbw->PixelSize()); - if (s_sk6812_grb) be_pushint(vm, s_sk6812_grb->PixelSize()); if (s_sk6812_grbw) be_pushint(vm, s_sk6812_grbw->PixelSize()); break; case 8: // # 08 : PixelCount void -> int if (s_ws2812_grb) be_pushint(vm, s_ws2812_grb->PixelCount()); - if (s_ws2812_grbw) be_pushint(vm, s_ws2812_grbw->PixelCount()); - if (s_sk6812_grb) be_pushint(vm, s_sk6812_grb->PixelCount()); if (s_sk6812_grbw) be_pushint(vm, s_sk6812_grbw->PixelCount()); break; case 9: // # 09 : ClearTo (color:??) -> void @@ -219,8 +191,6 @@ extern "C" { uint8_t g = (rgbw & 0xFF00) >> 8; uint8_t b = (rgbw & 0xFF); if (s_ws2812_grb) s_ws2812_grb->ClearTo(RgbColor(r, g, b)); - if (s_ws2812_grbw) s_ws2812_grbw->ClearTo(RgbwColor(r, g, b, 0)); - if (s_sk6812_grb) s_sk6812_grb->ClearTo(RgbColor(r, g, b)); if (s_sk6812_grbw) s_sk6812_grbw->ClearTo(RgbwColor(r, g, b, 0)); } break; @@ -233,8 +203,6 @@ extern "C" { uint8_t g = (rgbw & 0xFF00) >> 8; uint8_t b = (rgbw & 0xFF); if (s_ws2812_grb) s_ws2812_grb->SetPixelColor(idx, RgbColor(r, g, b)); - if (s_ws2812_grbw) s_ws2812_grbw->SetPixelColor(idx, RgbwColor(r, g, b, 0)); - if (s_sk6812_grb) s_sk6812_grb->SetPixelColor(idx, RgbColor(r, g, b)); if (s_sk6812_grbw) s_sk6812_grbw->SetPixelColor(idx, RgbwColor(r, g, b, 0)); } break; @@ -247,43 +215,12 @@ extern "C" { RgbColor rgb = s_ws2812_grb->GetPixelColor(idx); be_pushint(vm, (rgb.R << 16) | (rgb.G << 8) | rgb.B); } - if (s_ws2812_grbw) { - RgbwColor rgbw = s_ws2812_grbw->GetPixelColor(idx); - be_pushint(vm, (rgbw.W << 24) | (rgb.R << 16) | (rgb.G << 8) | rgb.B); - } - if (s_sk6812_grb) { - RgbColor rgb = s_sk6812_grb->GetPixelColor(idx); - be_pushint(vm, (rgb.R << 16) | (rgb.G << 8) | rgb.B); - } if (s_sk6812_grbw) { RgbwColor rgbw = s_sk6812_grbw->GetPixelColor(idx); be_pushint(vm, (rgbw.W << 24) | (rgb.R << 16) | (rgb.G << 8) | rgb.B); } } break; - // case 20: // # 20 : RotateLeft (rot:int [, first:int, last:int]) -> void - // case 21: // # 21 : RotateRight (rot:int [, first:int, last:int]) -> void - // case 22: // # 22 : ShiftLeft (rot:int [, first:int, last:int]) -> void - // case 23: // # 23 : ShiftRight (rot:int [, first:int, last:int]) -> void - // { - // int32_t rot = be_toint(vm, 3); - // int32_t first = -1; - // int32_t last = -1; - // if (argc >= 5) { - // first = be_toint(vm, 4); - // last = be_toint(vm, 5); - // } - // if (20 == cmd) { - // if (first >= 0) { strip->RotateLeft(rot, first, last); } else { strip->RotateLeft(rot); }; - // } else if (21 == cmd) { - // if (first >= 0) { strip->RotateRight(rot, first, last); } else { strip->RotateRight(rot); }; - // } else if (22 == cmd) { - // if (first >= 0) { strip->ShiftLeft(rot, first, last); } else { strip->ShiftLeft(rot); }; - // } else if (23 == cmd) { - // if (first >= 0) { strip->ShiftRight(rot, first, last); } else { strip->ShiftRight(rot); }; - // } - // } - // break; default: break; } From cb7d3ddb833a1b2b024f9dd9b39b9258f8a069d6 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Wed, 1 Dec 2021 23:02:45 +0100 Subject: [PATCH 175/185] Fix link in AWS CA --- tasmota/tasmota_ca.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/tasmota_ca.ino b/tasmota/tasmota_ca.ino index e77ce541d..ce78760b6 100644 --- a/tasmota/tasmota_ca.ino +++ b/tasmota/tasmota_ca.ino @@ -86,7 +86,7 @@ static const br_x509_trust_anchor PROGMEM LetsEncryptR3_TA = { /*********************************************************************************************\ * Amazon Root CA, RSA 2048 bits SHA 256, valid until 20380117 * - * https://letsencrypt.org/certificates/ + * https://www.amazontrust.com/repository/ * Downloaded from https://www.amazontrust.com/repository/AmazonRootCA1.pem * * to convert do: "bearssl ta AmazonRootCA1.pem" From 70d2903f8703f8cbbddb64ec185257dc3dca6129 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 2 Dec 2021 13:15:43 +0100 Subject: [PATCH 176/185] ESP32 core dev 2.0.1.2 should fix c3 ADC --- platformio_override_sample.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index 5d3175b06..d22b0b861 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -91,7 +91,7 @@ lib_extra_dirs = ${library.lib_extra_dirs} [env:tasmota32_base] ; *** Uncomment next lines ";" to enable development Tasmota Arduino version ESP32 ;platform = https://github.com/platformio/platform-espressif32.git#feature/arduino-idf-master -;platform_packages = framework-arduinoespressif32 @ https://github.com/tasmota/arduino-esp32/releases/download/2.0.1/framework-arduinoespressif32-release_IDF4.4.tar.gz +;platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/525/framework-arduinoespressif32-release_v4.4-7cac8278e.tar.gz ; platformio/tool-esptoolpy @ https://github.com/tasmota/esptool/releases/download/v3.2/esptool-v3.2.zip ; platformio/tool-mklittlefs @ ~1.203.200522 build_unflags = ${esp32_defaults.build_unflags} From 86628c9f5e5ef2cf5692f47eb45e3902ed9098fe Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 2 Dec 2021 14:02:22 +0100 Subject: [PATCH 177/185] Fix negative temperatures in NRF24 Fix negative temperatures in NRF24 (#13894) --- tasmota/xsns_61_MI_NRF24.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xsns_61_MI_NRF24.ino b/tasmota/xsns_61_MI_NRF24.ino index 2dd3b90e4..f5f61e4e3 100644 --- a/tasmota/xsns_61_MI_NRF24.ino +++ b/tasmota/xsns_61_MI_NRF24.ino @@ -1438,7 +1438,7 @@ void MINRFhandleATCPacket(void){ // AddLog(LOG_LEVEL_INFO,PSTR("NRF: ATC: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x"),MINRF.buffer.raw[0],MINRF.buffer.raw[1],MINRF.buffer.raw[2],MINRF.buffer.raw[3],MINRF.buffer.raw[4],MINRF.buffer.raw[5],MINRF.buffer.raw[6],MINRF.buffer.raw[7],MINRF.buffer.raw[8],MINRF.buffer.raw[9],MINRF.buffer.raw[10],MINRF.buffer.raw[11]); if(_slot==0xff) return; - MIBLEsensors[_slot].temp = (float)(__builtin_bswap16(_packet->temp))/10.0f; + MIBLEsensors[_slot].temp = (float)(int16_t(__builtin_bswap16(_packet->temp)))/10.0f; MIBLEsensors[_slot].hum = (float)_packet->hum; MIBLEsensors[_slot].bat = _packet->batPer; MIBLEsensors[_slot].eventType.tempHum = 1; From 9d643c2a4e4cf569a024a48064631751e813ae5b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 2 Dec 2021 15:48:55 +0100 Subject: [PATCH 178/185] Use Tasmota platformio framework fork --- platformio_tasmota32.ini | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index f832417ea..a28bef2d0 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -32,18 +32,13 @@ build_flags = ${esp_defaults.build_flags} -Wl,--wrap=panicHandler -Wl,--wrap=xt_unhandled_exception [core32] -platform = https://github.com/platformio/platform-espressif32.git#feature/arduino-idf-master -platform_packages = framework-arduinoespressif32 @ https://github.com/tasmota/arduino-esp32/releases/download/2.0.1.1/framework-arduinoespressif32-release_IDF4.4.tar.gz - platformio/tool-esptoolpy @ https://github.com/tasmota/esptool/releases/download/v3.2/esptool-v3.2.zip - platformio/tool-mklittlefs @ ~1.203.200522 +platform = https://github.com/tasmota/platform-espressif32.git#feature/arduino-idf-v4.4 build_unflags = ${esp32_defaults.build_unflags} build_flags = ${esp32_defaults.build_flags} [core32solo1] -platform = https://github.com/platformio/platform-espressif32.git#feature/arduino-idf-master +platform = https://github.com/tasmota/platform-espressif32.git#feature/arduino-idf-v4.4 platform_packages = framework-arduinoespressif32 @ https://github.com/tasmota/arduino-esp32/releases/download/2.0.1.1/framework-arduinoespressif32-solo1-release_IDF4.4.tar.gz - platformio/tool-esptoolpy @ https://github.com/tasmota/esptool/releases/download/v3.2/esptool-v3.2.zip - platformio/tool-mklittlefs @ ~1.203.200522 build_unflags = ${esp32_defaults.build_unflags} build_flags = ${esp32_defaults.build_flags} From f2d01d9ae9f6bf26ac6af2e95a073715e22e0609 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Thu, 2 Dec 2021 15:00:02 +0000 Subject: [PATCH 179/185] empty entry needed --- platformio_tasmota32.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index a28bef2d0..985374343 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -33,6 +33,7 @@ build_flags = ${esp_defaults.build_flags} [core32] platform = https://github.com/tasmota/platform-espressif32.git#feature/arduino-idf-v4.4 +platform_packages = build_unflags = ${esp32_defaults.build_unflags} build_flags = ${esp32_defaults.build_flags} From 44cf1b651200e041ca02284b5feeac735d4d623d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 2 Dec 2021 16:07:55 +0100 Subject: [PATCH 180/185] Update platformio_override_sample.ini --- platformio_override_sample.ini | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index d22b0b861..3bbbc9f44 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -89,11 +89,8 @@ lib_extra_dirs = ${library.lib_extra_dirs} [env:tasmota32_base] -; *** Uncomment next lines ";" to enable development Tasmota Arduino version ESP32 -;platform = https://github.com/platformio/platform-espressif32.git#feature/arduino-idf-master +; *** Uncomment next line ";" to enable development Tasmota Arduino version ESP32 ;platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/525/framework-arduinoespressif32-release_v4.4-7cac8278e.tar.gz -; platformio/tool-esptoolpy @ https://github.com/tasmota/esptool/releases/download/v3.2/esptool-v3.2.zip -; platformio/tool-mklittlefs @ ~1.203.200522 build_unflags = ${esp32_defaults.build_unflags} build_flags = ${esp32_defaults.build_flags} From d08369d1922c878d34fece20cd1934d86f79ae15 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 2 Dec 2021 20:52:25 +0100 Subject: [PATCH 181/185] new method is working --- .../Tasmota_build_development.yml.off | 1385 ----------------- 1 file changed, 1385 deletions(-) delete mode 100644 .github/workflows/Tasmota_build_development.yml.off diff --git a/.github/workflows/Tasmota_build_development.yml.off b/.github/workflows/Tasmota_build_development.yml.off deleted file mode 100644 index dd86c2e37..000000000 --- a/.github/workflows/Tasmota_build_development.yml.off +++ /dev/null @@ -1,1385 +0,0 @@ -name: Build_firmware_development - -on: - workflow_dispatch: # Manually start a workflow - push: - branches: development - paths-ignore: - - '.github/**' # Ignore changes towards the .github directory - - '**.md' # Do no build if *.md files changes - -jobs: - - tasmota: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-minimal: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-minimal - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-lite: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-lite - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-knx: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-knx - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-sensors: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-sensors - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-display: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-display - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-ir: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-ir - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-zbbridge: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-zbbridge - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-zigbee: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-zigbee - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-AF: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-AF - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-BG: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-BG - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-BR: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-BR - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-CN: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-CN - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-CZ: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-CZ - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-DE: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-DE - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-ES: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-ES - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-FR: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-FR - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-FY: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-FY - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-GR: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-GR - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-HE: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-HE - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-HU: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-HU - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-IT: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-IT - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-KO: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-KO - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-NL: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-NL - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-PL: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-PL - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-PT: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-PT - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-RO: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-RO - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-RU: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-RU - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-SE: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-SE - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-SK: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-SK - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-TR: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-TR - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-TW: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-TW - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-UK: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-UK - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota-VN: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota-VN - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32 - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32solo1: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32solo1 - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-webcam: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-webcam - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-odroidgo: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-odroidgo - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-core2: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-core2 - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-bluetooth: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-bluetooth - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-display: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-display - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-lvgl: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-lvgl - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-ir: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-ir - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - tasmota32c3: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32c3 - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - tasmota32-AF: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-AF - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-BG: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-BG - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-BR: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-BR - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-CN: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-CN - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-CZ: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-CZ - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-DE: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-DE - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-ES: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-ES - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-FR: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-FR - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-FY: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-FY - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-GR: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-GR - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-HE: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-HE - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-HU: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-HU - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-IT: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-IT - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-KO: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-KO - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-NL: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-NL - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-PL: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-PL - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-PT: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-PT - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-RO: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-RO - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-RU: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-RU - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-SE: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-SE - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-SK: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-SK - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-TR: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-TR - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-TW: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-TW - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-UK: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-UK - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - tasmota32-VN: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - - name: Install dependencies - run: | - pip install -U platformio - - name: Run PlatformIO - run: | - platformio run -e tasmota32-VN - - uses: actions/upload-artifact@v2 - with: - name: firmware - path: ./build_output - - - Upload: - needs: [tasmota-VN, tasmota32-VN, tasmota32-TW, tasmota32-TR] - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/download-artifact@v2 - with: - name: firmware - path: ./mv_firmware - - name: Display structure of downloaded files - run: ls -R - working-directory: ./mv_firmware - - name: Move firmware files in sub-folders - run: | - mkdir -p ./firmware/tasmota/languages - mkdir -p ./firmware/tasmota32/languages - mkdir -p ./firmware/map - [ ! -f ./mv_firmware/map/* ] || mv ./mv_firmware/map/* ./firmware/map/ - [ ! -f ./mv_firmware/firmware/tasmota.* ] || mv ./mv_firmware/firmware/tasmota.* ./firmware/tasmota/ - [ ! -f ./mv_firmware/firmware/tasmota-sensors.* ] || mv ./mv_firmware/firmware/tasmota-sensors.* ./firmware/tasmota/ - [ ! -f ./mv_firmware/firmware/tasmota-minimal.* ] || mv ./mv_firmware/firmware/tasmota-minimal.* ./firmware/tasmota/ - [ ! -f ./mv_firmware/firmware/tasmota-lite.* ] || mv ./mv_firmware/firmware/tasmota-lite.* ./firmware/tasmota/ - [ ! -f ./mv_firmware/firmware/tasmota-ir*.* ] || mv ./mv_firmware/firmware/tasmota-ir*.* ./firmware/tasmota/ - [ ! -f ./mv_firmware/firmware/tasmota-display.* ] || mv ./mv_firmware/firmware/tasmota-display.* ./firmware/tasmota/ - [ ! -f ./mv_firmware/firmware/tasmota-knx.* ] || mv ./mv_firmware/firmware/tasmota-knx.* ./firmware/tasmota/ - [ ! -f ./mv_firmware/firmware/tasmota-zbbridge.* ] || mv ./mv_firmware/firmware/tasmota-zbbridge.* ./firmware/tasmota/ - [ ! -f ./mv_firmware/firmware/tasmota-zigbee.* ] || mv ./mv_firmware/firmware/tasmota-zigbee.* ./firmware/tasmota/ - [ ! -f ./mv_firmware/firmware/tasmota32.* ] || mv ./mv_firmware/firmware/tasmota32.* ./firmware/tasmota32/ - [ ! -f ./mv_firmware/firmware/tasmota32solo1*.* ] || mv ./mv_firmware/firmware/tasmota32solo1*.* ./firmware/tasmota32/ - [ ! -f ./mv_firmware/firmware/tasmota32-ir*.* ] || mv ./mv_firmware/firmware/tasmota32-ir*.* ./firmware/tasmota32/ - [ ! -f ./mv_firmware/firmware/tasmota32-display.* ] || mv ./mv_firmware/firmware/tasmota32-display.* ./firmware/tasmota32/ - [ ! -f ./mv_firmware/firmware/tasmota32-lvgl.* ] || mv ./mv_firmware/firmware/tasmota32-lvgl.* ./firmware/tasmota32/ - [ ! -f ./mv_firmware/firmware/tasmota32-web*.* ] || mv ./mv_firmware/firmware/tasmota32-web*.* ./firmware/tasmota32/ - [ ! -f ./mv_firmware/firmware/tasmota32-odroidgo.* ] || mv ./mv_firmware/firmware/tasmota32-odroidgo.* ./firmware/tasmota32/ - [ ! -f ./mv_firmware/firmware/tasmota32-core2.* ] || mv ./mv_firmware/firmware/tasmota32-core2.* ./firmware/tasmota32/ - [ ! -f ./mv_firmware/firmware/tasmota32-bluetooth.* ] || mv ./mv_firmware/firmware/tasmota32-bluetooth.* ./firmware/tasmota32/ - [ ! -f ./mv_firmware/firmware/tasmota32c3*.* ] || mv ./mv_firmware/firmware/tasmota32c3*.* ./firmware/tasmota32/ - [ ! -f ./mv_firmware/firmware/tasmota32* ] || mv ./mv_firmware/firmware/tasmota32* ./firmware/tasmota32/languages/ - [ ! -f ./mv_firmware/firmware/* ] || mv ./mv_firmware/firmware/* ./firmware/tasmota/languages/ - - name: Display files to transfer - run: ls -R ./* - - name: Push Firmware files to https://github.com/arendst/Tasmota-firmware - uses: Jason2866/copy_file_to_another_repo_action@main - env: - API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }} - with: - source_file: 'firmware' - destination_repo: 'arendst/Tasmota-firmware' - user_email: 'github-actions@github.com' - user_name: 'github-actions' - - name: Creat trigger.txt - run: | - echo ${GITHUB_SHA} &> trigger.txt - echo "$( Date: Thu, 2 Dec 2021 22:14:47 +0100 Subject: [PATCH 182/185] Driver for '595 shift register --- tasmota/berry/drivers/Shift595.be | 80 +++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 tasmota/berry/drivers/Shift595.be diff --git a/tasmota/berry/drivers/Shift595.be b/tasmota/berry/drivers/Shift595.be new file mode 100644 index 000000000..3e22f9b33 --- /dev/null +++ b/tasmota/berry/drivers/Shift595.be @@ -0,0 +1,80 @@ +# Sample Relay driver for 595 shift registers +# ------------------------------------------------------------------------- +# You can cascade multiple '595 for a total of 28 relays (including other native relays) +# Include the following lines in 'preinit.be' +# import Shift595 +# tasmota.add_driver(Shift595(srclk,ser,rclk,count,inverted)) +# where +# srclk : GPIO number connected to the 595's SRCLK pin (serial shift clock) +# ser : GPIO number connected to the 595's SER pin (serial data in) +# rclk : GPIO number connected to the 595's RCLK pin (transfer to output) +# count : number of used output pins / relays (must be consecutive) +# inverted : if true, relay is driven by a 0/LOW inverted (instead of 1/HIGH) +# +# To use multiple '595, connects +# all SRCLK together to GPIO srclk +# all RCLK together to GPIO rclk +# GPIO ser to SER input of first '595 +# QH' output of first '595 to SER input of 2nd '595 and so on +# ------------------------------------------------------------------------- + +import string +import gpio + +class Shift595 + + var srclk, ser, rclk, count, inverted + var first, state + + def log_relay(relay) + var s = "" + for r:relay if r s+='1' else s+='0' end end + log("595: "+s,2) + end + + def shift_out(relay) + self.log_relay(relay) + + for i:0..size(relay)-1 + var bit + bit = (relay[size(relay)-1 - i]) ? int(!self.inverted) : int(self.inverted) + gpio.digital_write(self.srclk, 0) + gpio.digital_write(self.ser, bit) + gpio.digital_write(self.srclk, 1) + end + + gpio.digital_write(self.rclk, 1) + gpio.digital_write(self.rclk, 0) + gpio.digital_write(self.srclk, 0) + end + + def init(srclk, ser, rclk, count, inverted) + self.srclk= srclk + self.ser = ser + self.rclk = rclk + self.count = count + self.inverted = inverted + self.first = tasmota.global.devices_present + tasmota.global.devices_present += count + + gpio.pin_mode(self.srclk, gpio.OUTPUT) + gpio.pin_mode(self.ser, gpio.OUTPUT) + gpio.pin_mode(self.rclk, gpio.OUTPUT) + gpio.digital_write(self.srclk, 0) + gpio.digital_write(self.ser, 0) + gpio.digital_write(self.rclk, 0) + + self.state = 0 + end + + def set_power_handler(cmd, idx) + var new_state = tasmota.get_power()[self.first..self.first+self.count] + if self.state != new_state + self.state = new_state + self.shift_out(self.state) + end + end + +end + +return Shift595 # allow using 'import' instead of 'load()' From a437e92ed788bdb08ba5607c91731256a5577cc6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 2 Dec 2021 22:52:14 +0100 Subject: [PATCH 183/185] Use release Tasmota-platform-espressif32 instead of git version. Speeds up install. --- platformio_tasmota32.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index 985374343..5ef6f0463 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -32,14 +32,14 @@ build_flags = ${esp_defaults.build_flags} -Wl,--wrap=panicHandler -Wl,--wrap=xt_unhandled_exception [core32] -platform = https://github.com/tasmota/platform-espressif32.git#feature/arduino-idf-v4.4 +platform = https://github.com/tasmota/platform-espressif32/releases/download/v3.4.0/Tasmota-platform-espressif32.zip platform_packages = build_unflags = ${esp32_defaults.build_unflags} build_flags = ${esp32_defaults.build_flags} [core32solo1] -platform = https://github.com/tasmota/platform-espressif32.git#feature/arduino-idf-v4.4 +platform = https://github.com/tasmota/platform-espressif32/releases/download/v3.4.0/Tasmota-platform-espressif32.zip platform_packages = framework-arduinoespressif32 @ https://github.com/tasmota/arduino-esp32/releases/download/2.0.1.1/framework-arduinoespressif32-solo1-release_IDF4.4.tar.gz build_unflags = ${esp32_defaults.build_unflags} build_flags = ${esp32_defaults.build_flags} From aa123eff8c7f925853817051f8bfcfa79cc11e1f Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Fri, 3 Dec 2021 13:53:04 +0100 Subject: [PATCH 184/185] Fix compilation error --- tasmota/xdrv_40_telegram.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_40_telegram.ino b/tasmota/xdrv_40_telegram.ino index dacd85e0b..aebb2579a 100644 --- a/tasmota/xdrv_40_telegram.ino +++ b/tasmota/xdrv_40_telegram.ino @@ -83,7 +83,7 @@ bool TelegramInit(void) { if (!telegramClient) { telegramClient = new BearSSL::WiFiClientSecure_light(tls_rx_size, tls_tx_size); - if (Settings.flag5.tls_use_fingerprint) { + if (Settings->flag5.tls_use_fingerprint) { telegramClient->setPubKeyFingerprint(Telegram_Fingerprint, Telegram_Fingerprint, false); // check server fingerprint } else { telegramClient->setTrustAnchor(&GoDaddyCAG2_TA, 1); From 488c84e61b21ca920b7ab1f4a68b8b6147605298 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 3 Dec 2021 14:29:41 +0100 Subject: [PATCH 185/185] Fix JSON SSPM energy today/yesterday --- tasmota/xdrv_86_esp32_sonoff_spm.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/xdrv_86_esp32_sonoff_spm.ino b/tasmota/xdrv_86_esp32_sonoff_spm.ino index 808ada4c8..9f858691b 100644 --- a/tasmota/xdrv_86_esp32_sonoff_spm.ino +++ b/tasmota/xdrv_86_esp32_sonoff_spm.ino @@ -1117,13 +1117,13 @@ void SSPMEnergyShow(bool json) { #ifdef SSPM_JSON_ENERGY_YESTERDAY ResponseAppend_P(PSTR("],\"" D_JSON_YESTERDAY "\":[")); for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { - ResponseAppend_P(PSTR("%s%*_f"), (i>0)?",":"", -1, &Sspm->energy_today[i >>2][i &3]); + ResponseAppend_P(PSTR("%s%*_f"), (i>0)?",":"", -1, &Sspm->energy_yesterday[i >>2][i &3]); } #endif #ifdef SSPM_JSON_ENERGY_TODAY ResponseAppend_P(PSTR("],\"" D_JSON_TODAY "\":[")); for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { - ResponseAppend_P(PSTR("%s%*_f"), (i>0)?",":"", -1, &Sspm->energy_yesterday[i >>2][i &3]); + ResponseAppend_P(PSTR("%s%*_f"), (i>0)?",":"", -1, &Sspm->energy_today[i >>2][i &3]); } #endif ResponseAppend_P(PSTR("],\"" D_JSON_ACTIVE_POWERUSAGE "\":["));